Entity Framework 4: плохая производительность с SQL Server 2008 - PullRequest
3 голосов
/ 08 октября 2010

Я разрабатываю программное обеспечение на основе Entity Framework для обработки данных в базе данных MS SQL Server 2008.

[Проблема 1]

Я только чтоПопытка вставить некоторые небольшие данные ( около 2 МБ ) из моей программы в базу данных: производительность очень плохая!Для вставки этих данных требуется более 1 минуты !

Я пытаюсь сгенерировать предварительно скомпилированные представления, у меня такие же результаты: - (

Весь мой код использует бизнес-уровень (автоматически сгенерированный из файла .edmx с шаблоном T4) для управления данными в слое обслуживания. Очень удобно ориентироваться в отношениях объектов.

Как я могуповысить производительность этих вставок с помощью Entity Framework?

[Trouble 2]

Кроме того, перед вставкой данных в базу данных методом SaveChanges () я заполняюмой объектный контекст с помощью метода AddObject (). Я добавляю около 100 000 небольших объектов (около 2 Мб) в свой объектный контекст с помощью AddObject (): это занимает очень много времени (более 10 минут)!

Как я могу уменьшить это время?

ОБНОВЛЕНИЕ

Моя программа должна сохранить более 50 МБ в базе данных менее чем за 2-3 минуты?Вы думаете, это будет возможно с EF?

Ответы [ 8 ]

4 голосов
/ 08 октября 2010

Вы можете использовать Entity Framework Profiler , чтобы проверить, какой SQL генерируется.Этот инструмент имеет 30-дневную бесплатную пробную версию.Также утверждается, что он может выполнять «Анализ и обнаружение распространенных ошибок при использовании Entity Framework».

Существует также эта статья по настройке EF

Редактировать

На основании ваших правок EF не подходит,Вам нужно выполнить массовую вставку, чтобы быстро получить данные.Взгляните на эту ссылку, где я помог кому-то сократить время загрузки с 10 часов до 6 минут.

2 голосов
/ 16 октября 2012

EF (и LINQ2SQL в этом отношении) выполняет одно обновление / вставку для каждой записи.Это обычно приводит к менее приемлемой производительности для массовых вставок / обновлений.Обходной путь заключается в создании хранимых процедур, которые будут выполнять эти задачи за вас.Это приемлемое решение в большинстве случаев, когда вы выполняете эти операции с небольшим количеством типов объектов, и в этом случае все еще возможно использовать EF, записать эти SP вручную и затем добавить их в EDMX.Вы можете Google для использования хранимых процедур в EF.

2 голосов
/ 08 октября 2010

Здесь есть несколько возможностей.

  1. Аппаратное обеспечение базы данных может не соответствовать задаче обработки 100 000 вставок. Сколько таблиц задействовано? Существуют ли вспомогательные факторы, такие как запускающие устройства? Ограничена ли память базы данных?

  2. Аппаратное обеспечение веб-сервера может не соответствовать задаче обработки такой большой нагрузки. Откуда берутся данные? Сколько времени занимает перевод на веб-сервер? Сколько операций вставки / с фактически отправляет веб-сервер серверу базы данных?

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

Вам необходимо запустить профилировщик на веб-сервере и использовать SQL Profiler на сервере базы данных. Кроме того, при загрузке данных вы должны следить за графиками загрузки процессора, памяти и сети обоих компьютеров.

Получив все эти данные, вы сможете точно определить, в чем проблема.

UPDATE
Как примечание, EF должен создать не менее 100 000 объектов для хранения данных, которые вы загружаете (по одному для каждой записи). У этого есть свои издержки, поэтому ORM обычно не очень хорошая идея для крупномасштабной вставки / обновления данных.

ОБНОВЛЕНИЕ 2
Если вы используете и клиент, и сервер базы данных на одном и том же настольном компьютере, то у вас могут возникнуть проблемы с оборудованием. Надеюсь, у вас есть многоядерная система с минимум 4 ГБ оперативной памяти. Все в вашей системе будет конкурировать за ресурсы: Visual Studio, SQL Server, само приложение, а также все, что вы запускаете. Studio и SQL Server - это нагрузка на память и процессор. (К вашему сведению - сервер SQL не сообщает обо всем диспетчеру задач)

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

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

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

Это очень медленно при запускена многих объектах, особенно если время обращения к серверу базы данных превышает 1 миллисекунду.

Чтобы повысить производительность при сохранении многих объектов в базе данных, используйте класс SqlBulkCopy вместо Entity Framework.

Полное сравнение между Entity Framework и SqlBulkCopy можно найти в этой статье: Как массово вставить сложные объекты в базу данных SQL Server

1 голос
/ 10 октября 2010

В исходном вопросе у меня сложилось впечатление, что около 100 000 или около того объектов создаются сразу, и выполняется один вызов SaveChanges. Такая крупная единица работы, когда требуется один вызов SaveChanges, почти всегда является очень плохой идеей производительности для Entity Framework. Я попытался бы разделить вещи на серию пакетов по 100 или около того объектов и вызывать SaveChanges между каждой группой. Фактически, я бы даже избавился от контекста и создал новый между партиями, потому что в противном случае вы получите все эти объекты сразу в менеджере состояний, что приведет к накладным расходам. Возможно, вам придется поэкспериментировать с различными размерами партий, чтобы найти наилучшее число.

Кроме того, вы можете подумать, какой тип сущностей вы используете. Если вы используете сущности poco, есть некоторые накладные расходы на обнаружение изменений, которых нет при использовании классов, которые реализуют IEntityWithChangeTracking (или наследуют от EntityObject, реализующего этот интерфейс).

  • Danny
1 голос
/ 08 октября 2010

Скорее всего, виновником является не Entity Framework, а схема базы данных, например, плохие кластеризованные индексы или слишком много индексов.

Вы можете увидеть SQL, сгенерированный Entity Framework, используя Свойство ObjectQuery.ToTraceString .

Если SQL, сгенерированный Entity Framework, не удовлетворяет вашим потребностям, вы можете использовать собственные хранимые процедуры для операций создания, обновления и удаления.

1 голос
/ 08 октября 2010

Вы можете профилировать запросы с помощью SQL Server Profiler, а затем использовать помощник по настройке ядра СУБД для определения лучшей статистики и добавляемых индексов.

0 голосов
/ 08 октября 2010

У меня возникла похожая проблема с моим текущим проектом.Я подключился к SQL Profiler и начал процесс.Похоже, что Entity Framework запускает SQL-транзакцию для каждого INSERT или UPDATE каждый раз, когда сохраняются изменения.

Я не уверен, что это как-то связано с проблемой, но я бы запустил SQL Profiler иизучить результаты.Я также отслеживал бы использование вашего диска (чтение и запись) на вашем блоке SQL (если это возможно) и проверял бы наличие красных флажков.

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