Entity Framework Алгоритм объединения данных - PullRequest
6 голосов
/ 27 апреля 2011

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

У нас есть набор данных в таблице T. Из этого мы извлекаем набор, который будем называть A. Мы также запрашиваем канал XML иполучить набор, который мы назовем X.

  • Если значение из X находится в A, запись в A должна быть обновлена, чтобы отразить данные для X.record
  • Если значение из Xне в A, X.record должен быть вставлен в A
  • Если значение из A не в X, A.record должен быть сохранен в A
  • X должен быть полностью повторен длявсе записи и A должны быть обновлены

Все эти изменения необходимо вставить обратно в базу данных.

Алгоритм в соответствии с настройкой выполняет следующие действия:

Query XML into a LIST
foreach over the XML LIST
    look up foreach.item in A via LINQ (i.e. query = from record in A where
                                                         record.GUID == foreach.item.GUID
                                                         select record)
    if query.Count() == 0
        insert into A (via context.AddToTableName(newTableNameObject)
    else
        var currentRecord = query.First()
        set all properties on currentRecord = properties from foreach.item
        context.SaveChanges()

Я знаю, что это неоптимально.Я попытался поместить A в объект (назовем его queryA) вне цикла foreach, пытаясь переместить запрос в память и не ударить по диску, но, подумав об этом, я понял, что база данных уже находится в памяти.

После добавления объектов таймера в алгоритм ясно, что больше всего времени стоит вызов функции SaveChanges ().В некоторых случаях это 20 мс, а в некоторых, по-видимому, он будет прыгать до 100 мс.

Я бы предпочел вызывать SaveChanges () только один раз.Я не могу понять, как это сделать, учитывая мои глубокие познания в EF (в лучшем случае тонкие) и ограничения, связанные с невозможностью изменить структуры таблиц и необходимостью сохранять данные из A, которого нет в X.

Предложения?

1 Ответ

5 голосов
/ 27 апреля 2011

Не думаю, что вы улучшите производительность при использовании Entity Framework:

Запрос

  • Загрузка каждой записи отдельным запросом нехорошо
  • Вы можете повысить производительность, загрузив несколько записей в одном запросе.Например, вы можете загрузить небольшую партию записей, используя либо ||в состоянии или Contains (например, IN в SQL).Contains поддерживается только .NET 4.0.
  • Другим улучшением может быть замена запроса хранимой процедурой и табличным параметром для передачи всех направляющих в соединение SQL Server A с X.Guids и получения результатов.Табличные значения параметров поддерживаются только в SQL 2008 и новее.

Изменение данных

  • Вам не нужно не следует звонить SaveChanges после каждой модификации.Вы можете вызвать его после цикла foreach, и он все равно будет работать.Он пройдет все модификации в одной транзакции , но вы не получите никакого повышения производительности при такой операции , и согласно этот ответ может дать вам значительное повышение.
  • EF не поддерживает пакетирование команд , и поэтому каждое обновление или вставка всегда выполняет отдельную обратную передачу в базу данных.При использовании EF для изменения данных нет никакого способа обойти это, кроме как полностью реализовать новый поставщик ADO.NET EF (это все равно, что начинать новый проект).
  • Опять же, решение заключается в сокращении количества обращений с помощью хранимой процедуры с табличным параметром.
  • Если ваша БД также использует этот GUID в качестве первичного ключа и кластерного индекса, у вас будет еще одно снижение производительности на переупорядочение индекса после каждой вставки = изменение данных на диске.

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

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