Entge Framework слияния не отслеживает плохую производительность - PullRequest
45 голосов
/ 13 февраля 2012

У меня странное поведение при попытке выполнить запрос, объявляющий ObjectQuery MergeOption для "NoTracking", в этом случае структура сущности не должна присоединять какую-либо сущность и не создавать относительную ObjectStateEntry для отслеживания состояния сущности.

Проблемав том, что вместо увеличения производительности он ухудшается, тот же запрос занимает 10 секунд с объединением по умолчанию (то есть AppendingOnly) и больше 1 минут, если я пытаюсь указать notracking

У кого-нибудь есть объяснение этому?

1 Ответ

143 голосов
/ 13 февраля 2012

Если вы отключите отслеживание изменений, установив параметр слияния NoTracking, вы сэкономите затраты на производительность при присоединении объектов к контекстам, но с другой стороны вы также потеряете управление идентификацией.

Это означает, что потенциально гораздо большеобъекты - многие с одним и тем же ключом - будут материализованы.

Пример. Предположим, у вас есть объект User с коллекцией Roles в качестве свойства навигации.Также предположим, что у вас есть 1 миллион пользователей в базе данных, и все пользователи находятся в одних и тех же 10 ролях, т.е. у каждого пользователя есть коллекция ролей с 10 элементами.Если вы выполните следующий запрос ...

var users = context.Users.Include("Roles").ToList();

... количество материализованных и созданных экземпляров объектов зависит от опции объединения:

  • Если вы неПри использовании NoTracking у вас будет 1.000.010 объектов в памяти, а именно 1 миллион пользователей, но только 10 ролей, поскольку сопоставление идентификаторов гарантирует, что только 1 роль на ключ будет материализована и присоединена к контексту.Те же 10 экземпляров роли используются для всей коллекции Roles всех пользователей.

  • Однако, если вы используете NoTracking, EF не будет прикреплять объекты к контексту, поэтому управление идентификацией отключенои у вас будет 11 000 000 объектов в памяти: 1 миллион пользователей и 10 экземпляров ролей на пользователя, то есть 10 миллионов объектов ролей.Таким образом, у вас в 10 раз больше материализованных объектов по сравнению с объектами, присоединенными к контексту.

Материализация объекта классифицируется как «умеренные» затраты производительности :

Операция: Материализация объектов Относительная стоимость: умеренная Частота: один раз для каждого объекта, возвращаемого запросом. Комментарии: Процесс чтения возвращенного объекта DbDataReader, создания объектов и установки значений свойств на основе значений в каждом экземпляре класса DbDataRecord. Если объект уже существует в ObjectContext и запрос использует параметры слияния AppendOnly или PreserveChanges , этот этап не влияет на производительность.

Другими словами: если в запросе используется параметр слияния NoTracking, этот этап не влияет на производительность , и может быть возможно, что выигрыш в производительности от отключения отслеживания изменений будет разрушен недостатками отключенного идентификаторауправление и материализация умноженного объекта.

...