|
|
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
Добрый день, Пробую возможности Entiry Framework 4.0 (Visual Studio 2010 RC). До этого работал с Hibernate 2.1. И так... Есть маппинг (см рисунок). В БД Таблица Managers нстедуется от Persons. делаю запрос в C# Код: plaintext 1. 2. 3. 4. 5. Смотрю в профйлер: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. В запросе используется таблица Managers, которая мне не нужна !!! В Execution plan видно, что cost ображения в Managers 51%. Т.е. это БОЛЬШЕ ПОЛОВИНЫ ! Кроме того, Код: plaintext 1. 2. 3. 4. 5. 6. не изменяет запрос. Хотя в описании OfType написано // Summary: // Limits the query to only results of a specific type. Плиз, побскажите, где я ошибся.... Спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.02.2010, 11:31 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
А вот и план ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.02.2010, 11:33 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
Even more, Код: plaintext 1. Всеравно делает обращение в Managers ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 16.02.2010, 11:44 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
Ну, то, что при простом обращении Код: plaintext Вариантов 2: - или вытаскивать все, что в принципе может пригодится, 1 запросом. - либо достать ведущую таблицу, определить тип каждого элемента и для тех, кто не "не просто персона" - достать еще дополнительные поля (этакая Lazy-инициализация). В большинстве случаев первый вариант предпочтительнее. По крайней мере, на сколько я помню, в NH реализация аналогичная. Почему не срабатывает Код: plaintext Собственно, в описании метода OfType есть такая ремарка: A new ObjectQuery(T) instance that is equivalent to the original instance with OFTYPE applied. Соответсвенно, если посмотреть на описание оператора OFTYPE , то можно увидеть что он возвращает все объекты приводимые (т.е. унаследованные от ...) к указанному типу, кроме случая, когда указана опция ONLY . В принципе, это поведение полностью соответствует семантике для OfType, которое описано в статье The .NET Standard Query Operators , а именно: The OfType operator filters the elements of a sequence based on a type. Думаю, в формальной спецификации C# будет описано аналогичное поведение - в выборку попадает как базовый, так и наследуемые типы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 10:07 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
МихаилРНу, то, что при простом обращении Код: plaintext А это не имеет значения, т.к. менеджер это тоже персона. Если я говорю - хочу список персон, то мне не важно какой тип у персоны, менеджер, стедент, и т.д. Мне нужен базовый тип, список всех персон. МихаилР Вариантов 2: - или вытаскивать все, что в принципе может пригодится, 1 запросом. - либо достать ведущую таблицу, определить тип каждого элемента и для тех, кто не "не просто персона" - достать еще дополнительные поля (этакая Lazy-инициализация). В большинстве случаев первый вариант предпочтительнее. По крайней мере, на сколько я помню, в NH реализация аналогичная. 1) Не желательно, вполне возможно, что большенство данных не понадобятся. 2) Это порождает ображение к другим таблицам. NHibernate дает ровно столько, сколько от него просишь дать. При этом SQL получается лучше. МихаилР Почему не срабатывает Код: plaintext Собственно, в описании метода OfType есть такая ремарка: A new ObjectQuery(T) instance that is equivalent to the original instance with OFTYPE applied. Соответсвенно, если посмотреть на описание оператора OFTYPE , то можно увидеть что он возвращает все объекты приводимые (т.е. унаследованные от ...) к указанному типу, кроме случая, когда указана опция ONLY . В принципе, это поведение полностью соответствует семантике для OfType, которое описано в статье The .NET Standard Query Operators , а именно: The OfType operator filters the elements of a sequence based on a type. Думаю, в формальной спецификации C# будет описано аналогичное поведение - в выборку попадает как базовый, так и наследуемые типы. Спасибо за подробный ответ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 11:04 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
Я нашел способ получения правильного запроса, т.е. только по таблице Persons. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 11:28 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
авторА это не имеет значения, т.к. менеджер это тоже персона. Именно! Хорошо, вот смотрите простейший пример (модификация вашего): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Как вы думете, если бы EF обращался только к таблице персон, то как бы ему пришлось реализовывать данный код? Логично, что ему пришлось бы в момент кастинга (или при первом обращении EmployeeNumber) заново лезть в базу всего лишь за 1 полем! А теперь представьте, сколько таких запросов он сгенерирует всего за один проход? Выгоднее, вытянуть все сразу. Кстати, расскажите как работает NH, я помню, что он может использовать proxy для связанных сущностей, но не помню, чтобы proxy использовались при прямой загрузки (впрочем, возможно, можно выставить и такие опции для Lazy-загрузки). Только вот даже если это возможно, не уверен, что вы что-то выиграете от оптимизации всего 1-го запроса. Проиграете на последующих. А если вас смущают накладные на подцепление таблицы, то вообще-то Table-per-Type не самый оптимальный вариант мапинга, для многих задач Table-per-Hierarchy - гораздо удобнее. Именно потому, что все схожие типы в одной таблице. NHibernate дает ровно столько, сколько от него просишь дать. При этом SQL получается лучше. У меня сложилось обратное впечатление - нужно очень четко понимать что будет делать NH, чтобы не влипнуть в деградацию производительности. Причем Lazy-загрузка - это лидер по количеству ошибок неикушенных разработчиков. Я нашел способ получения правильного запроса, т.е. только по таблице Persons Поделитесь, если не сложно, интересно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 13:18 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
МихаилРавторА это не имеет значения, т.к. менеджер это тоже персона. Именно! Хорошо, вот смотрите простейший пример (модификация вашего): Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Как вы думете, если бы EF обращался только к таблице персон, то как бы ему пришлось реализовывать данный код? Если я указываю, что мне нужно получить персон - это значит, что мне нужны персоны. Такой код работать не должен, конечно хорошо, со стороны C#, что так можно, но это не то, что мне нужно. Вообщем должны быть варианты. МихаилР Логично, что ему пришлось бы в момент кастинга (или при первом обращении EmployeeNumber) заново лезть в базу всего лишь за 1 полем! А теперь представьте, сколько таких запросов он сгенерирует всего за один проход? Выгоднее, вытянуть все сразу. Описанный сценарий записи от конкретной решаемой задачи. Впролне вероятно, что в Persons у меня попадут 1-2 записи. В этом случае не будет большой проблемой сходить на sql за 1 полем. А вообще, нужно иметь возможность более тонкого тюнинга. МихаилР Кстати, расскажите как работает NH, я помню, что он может использовать proxy для связанных сущностей, но не помню, чтобы proxy использовались при прямой загрузки (впрочем, возможно, можно выставить и такие опции для Lazy-загрузки). Только вот даже если это возможно, не уверен, что вы что-то выиграете от оптимизации всего 1-го запроса. Проиграете на последующих. Вынужден констатировать факт, что NHibernate, зараза, поступает почти так же. Но, SQL более вменяемый генерит. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. NHibernate, в этом пока ведет. МихаилР А если вас смущают накладные на подцепление таблицы, то вообще-то Table-per-Type не самый оптимальный вариант мапинга, для многих задач Table-per-Hierarchy - гораздо удобнее. Именно потому, что все схожие типы в одной таблице. Меня смущает не возможность контролировать обязательность полей, в схеме TPH. А в производительности, да, быстрее. МихаилР NHibernate дает ровно столько, сколько от него просишь дать. При этом SQL получается лучше. У меня сложилось обратное впечатление - нужно очень четко понимать что будет делать NH, чтобы не влипнуть в деградацию производительности. Причем Lazy-загрузка - это лидер по количеству ошибок неикушенных разработчиков. Я нашел способ получения правильного запроса, т.е. только по таблице Persons Поделитесь, если не сложно, интересно. Все очень просто: Код: plaintext 1. 2. 3. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 14:23 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
Dmitry Sukhovilin, Вынужден констатировать факт, что NHibernate, зараза, поступает почти так же. Но, SQL более вменяемый генерит Собственно, если вы немного поразмышляете над моим примером, то придете к выводу, что другой вариант, это только Lazy-инициализация, а она почти всегда слишком накладна. А вменяемость кода... Ничего не могу сказать - вроде план запроса для первого вашего варианта и так оптимальный для такого варианта, хоть использовать подзапрос, хоть нет. Меня смущает не возможность контролировать обязательность полей, в схеме TPH. А в производительности, да, быстрее. Не очень понял, если честно. Вы имеете в виду, что нельзя указать поле как необязательное в предке, а затем сделать его обязательным в потомке? Если да, то и в TPT для EF это вроде не возможно... Или вы о чем-то другом? Все очень просто Ну, да, логично :). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 14:45 |
|
||
|
Негерация запросов в EF 4.0
|
|||
|---|---|---|---|
|
#18+
МихаилРDmitry Sukhovilin, Вы имеете в виду, что нельзя указать поле как необязательное в предке, а затем сделать его обязательным в потомке? Если да, то и в TPT для EF это вроде не возможно... Или вы о чем-то другом? Нельзя гарантировать на уровне БД обязательность поля. В TPT я могу сказать, что EmployeeCount должно не сожержать NULL, в TPH так нельзя, это большой "-". ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.02.2010, 15:23 |
|
||
|
|

start [/forum/topic.php?fid=17&fpage=62&tid=1351457]: |
0ms |
get settings: |
9ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
54ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
42ms |
get tp. blocked users: |
1ms |
| others: | 216ms |
| total: | 354ms |

| 0 / 0 |
