Минимизируйте обновления базы данных от изменений в DataTable / SqlDataAdapter - PullRequest
1 голос
/ 30 июля 2009

Моя цель - максимизировать производительность. Основы сценария:

  • Я считал некоторые данные из SQL Server 2005 в таблицу данных (1000 записей x 10 столбцов)
  • Я выполняю некоторую обработку в .NET данных, все записи имеют как минимум 1 поле, измененное в DataTable, но потенциально все 10 полей могут быть изменены
  • Я также добавляю несколько новых записей в таблицу данных
  • Я делаю SqlDataAdapter.Update (myDataTable.GetChanges ()), чтобы сохранить обновления (вставки) обратно в БД, используя InsertCommand и UpdateCommand, которые я определил в начале
  • Предположим, что обновляемая таблица содержит 10 миллионов записей

Это хорошо. Однако, если строка в DataTable изменилась, тогда ВСЕ столбцы для этой записи обновляются в базе данных, даже если только 1 из 9 столбцов фактически изменил значение. Это означает ненужную работу, особенно если задействованы индексы. Я не верю, что SQL Server оптимизирует этот сценарий?

Я думаю, что если бы мне удалось обновить только столбцы, которые фактически изменились для любой данной записи, я бы увидел заметное улучшение производительности (особенно в совокупности, я буду иметь дело с миллионами строк).

Я нашел эту статью: http://netcode.ru/dotnet/?lang=&katID=30&skatID=253&artID=6635 Но не нравится идея сделать несколько обновлений внутри sproc. Если не считать создания отдельных операторов UPDATE для каждого измененного DataRow, а затем запускать их каким-то образом в пакете, я ищу опыт / предложения других людей.

(Пожалуйста, предположите, что я не могу использовать триггеры)

Заранее спасибо

Редактировать: Любой способ получить SqlDataAdapter для отправки операторов UPDATE, специфичных для каждого измененного DataRow (только для обновления фактических измененных столбцов в этой строке), вместо предоставления общего .UpdateCommand, который обновляет все столбцы?

Ответы [ 3 ]

2 голосов
/ 05 августа 2009

Разве невозможно реализовать собственный IDataAdapter, где вы реализуете эту функцию?

Конечно, DataAdapter запускает только правильную SqlCommand, которая определяется RowState каждого DataRow. Таким образом, это означает, что вам нужно будет сгенерировать команду SQL, которая должна выполняться для каждой ситуации ...

Но мне интересно, стоит ли это усилий. Сколько производительности вы получите?
Я думаю, что - если это действительно необходимо - я бы отключил все свои индексы и ограничения, сделал бы обновление, используя обычный SqlDataAdapter, а затем включил индексы и ограничения.

0 голосов
/ 06 августа 2009

Я бы ОЧЕНЬ рекомендовал сделать это с помощью хранимой процедуры. Допустим, у вас есть 10 миллионов записей, которые вы должны обновить. И скажем, что каждая запись имеет 100 байтов (для 10 столбцов это может быть слишком мало, но давайте будем консервативны). Это составляет около 100 МБ данных, которые должны быть переданы из базы данных (сетевой трафик), сохранены в памяти и затем возвращены в базу данных в форме UPDATE или INSERT, которые являются гораздо более подробными для передачи в базу данных.

Я ожидаю, что SP будет работать намного лучше.

Чем снова вы можете разделить вашу работу на меньшие SP (которые вызываются из основного SP), которые обновят только необходимые поля и таким образом увеличат производительность.

Отключение индексов / ограничений также является опцией.

EDIT:
Еще одна вещь, которую вы должны учитывать, это потенциальное количество различных операторов обновления. В случае 10 полей в строке любое поле может остаться прежним или измениться. Поэтому, если вы сконструируете свой оператор UPDATE, чтобы отразить это, вы могли бы потенциально получить 10 ^ 2 = 1024 различных операторов UPDATE, и любой из них должен быть проанализирован SQL Server, рассчитан план выполнения и проанализированный оператор сохранен в некоторой области. Есть цена, чтобы сделать это.

0 голосов
/ 05 августа 2009

Вы можете попробовать создать XML-файл вашего измененного набора данных, передать его в качестве параметра sproc и выполнить одно обновление, используя функцию sql node () для перевода xml в табличную форму.

вы никогда не должны пытаться обновить кластерный индекс. если вы это сделаете, пришло время переосмыслить вашу схему БД.

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