Почему вставка объектов в EF 4.1 такая медленная по сравнению с ObjectContext? - PullRequest
79 голосов
/ 10 мая 2011

Обычно я вставляю 35000 объектов в одну транзакцию:

using(var uow = new MyContext()){
  for(int i = 1; i < 35000; i++) {
     var o = new MyObject()...;
     uow.MySet.Add(o);
  }
  uow.SaveChanges();
}

Это займет вечность! Если я использую базовый ObjectContex t (используя IObjectAdapter), он все еще медленный, но занимает около 20 секунд. Похоже, DbSet<> выполняет линейный поиск, который занимает квадратное время ...

Кто-нибудь еще видел эту проблему?

Ответы [ 4 ]

124 голосов
/ 10 мая 2011

Как уже указывал Ладислав в комментарии, вам нужно отключить автоматическое обнаружение изменений для повышения производительности:

context.Configuration.AutoDetectChangesEnabled = false;

Это обнаружение изменений включено по умолчанию в DbContext API.

Причина, по которой DbContext ведет себя так сильно отличается от API ObjectContext, заключается в том, что гораздо больше функций API DbContext будут вызывать DetectChanges внутри, чем функции ObjectContext API, когда включено автоматическое обнаружение изменений.1012 *

Здесь вы можете найти список тех функций, которые по умолчанию вызывают DetectChanges.Это:

  • Add, Attach, Find, Local или Remove членов DbSet
  • GetValidationErrors, Entry или SaveChanges членов на DbContext
  • Метод Entries на DbChangeTracker

Особенно Add звонки DetectChanges, который отвечает за бедныхпроизводительность, которую вы испытали.

Я противопоставляю этому ObjectContext API-вызовы DetectChanges только автоматически в SaveChanges, но не в AddObject и других соответствующих методах, упомянутых выше.Вот почему производительность по умолчанию для ObjectContext выше.

Почему они внедрили это автоматическое обнаружение изменений по умолчанию в DbContext во многих функциях?Я не уверен, но похоже, что его отключение и вызов DetectChanges вручную в нужных точках считается продвинутым и может легко внести незначительные ошибки в ваше приложение, поэтому используйте [it] с осторожностью .

11 голосов
/ 18 марта 2012

Маленький эмпирический тест с EF 4.3 CodeFirst:

Удалено 1000 объектов с AutoDetectChanges = true: 23 сек.

Удалено 1000 объектов с AutoDetectChanges = false: 11 секунд

Вставлено 1000 объектов с AutoDetectChanges = true: 21 сек

Вставлено 1000 объектов с AutoDetectChanges = false: 13 секунд

4 голосов
/ 11 октября 2017

В .netcore 2.0 это было перемещено в:

context.ChangeTracker.AutoDetectChangesEnabled = false;

1 голос
/ 06 апреля 2013

Кроме ответов, которые вы нашли здесь.Важно знать, что на уровне базы данных больше работы для вставки, чем для добавления.База данных должна расширять / выделять новое пространство.Затем он должен обновить хотя бы индекс первичного ключа.Хотя индексы также могут обновляться при обновлении, это гораздо реже.Если есть какие-либо внешние ключи, он должен прочитать эти индексы, чтобы убедиться, что ссылочная целостность поддерживается.Триггеры также могут играть роль, хотя они могут влиять на обновления одинаково.

Вся эта работа с базой данных имеет смысл в ежедневной операции вставки, создаваемой записями пользователей.Но если вы просто загружаете существующую базу данных или имеете процесс, который генерирует много вставок.Возможно, вы захотите посмотреть на способы ускорить это, отложив его до конца.Обычно отключение индексов при вставке является обычным способом.Есть очень сложные оптимизации, которые могут быть выполнены в зависимости от случая, они могут быть немного подавляющими.

Просто знайте, что в целом вставка займет больше времени, чем обновления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...