Алгоритм структуры сущности для объединения данных

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

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

  • Если значение из X находится в 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

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

Запрос

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

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

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

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