Лучшие практики для вставки / обновления большого объема данных в SQL Server 2008
Я строю систему для обновления больших объемов данных через различные каналы CSV. Обычно я просто зацикливаю каждую строку в ленте, выполняю запрос на выборку, чтобы проверить, существует ли элемент, и вставляет / обновляет элемент в зависимости от того, существует он или нет.
Я чувствую, что этот метод не очень масштабируемый и может забить сервер на большие каналы. Мое решение состоит в том, чтобы перебирать элементы как обычно, но сохранять их в памяти. Затем для каждых 100 или около того элементов сделайте выбор из этих 100 элементов и получите список существующих элементов в базе данных, которые соответствуют. Затем объедините операторы вставки / обновления и запустите их в базу данных. Это существенно сократило бы поездки в базу данных.
Является ли это достаточно масштабируемым решением, и есть ли примеры учебных пособий по импорту больших фидов в продуктивную среду?
Спасибо
5 ответов
Поскольку вы используете SQL Server 2008, я бы порекомендовал этот подход:
- сначала скопируйте ваши CSV-файлы в промежуточную таблицу
- обновить целевую таблицу из этой промежуточной таблицы с помощью команды MERGE
Посмотрите документы MSDN и отличный пост в блоге о том, как использовать команду MERGE.
По сути, вы создаете связь между вашей фактической таблицей данных и промежуточной таблицей по общим критериям (например, по общему первичному ключу), а затем вы можете определить, что делать, когда
- строки совпадают, например, строка существует как в исходной, так и в целевой таблице -> обычно вы либо обновляете некоторые поля, либо просто игнорируете их все вместе
- строка из источника не существует в цели -> как правило, для вставки
Вы бы имели MERGE
Заявление примерно так:
MERGE TargetTable AS t
USING SourceTable AS src
ON t.PrimaryKey = src.PrimaryKey
WHEN NOT MATCHED THEN
INSERT (list OF fields)
VALUES (list OF values)
WHEN MATCHED THEN
UPDATE
SET (list OF SET statements)
;
Конечно, ON
пункт может быть гораздо более сложным, если это необходимо. И, конечно же, ваш WHEN
утверждения также могут быть более сложными, например,
WHEN MATCHED AND (some other condition) THEN ......
и так далее.
MERGE
это очень мощная и очень полезная новая команда в SQL Server 2008 - используйте ее, если можете!
Ваш путь - худшее из возможных решений. В общем, вы не должны думать с точки зрения циклического прохождения записей по отдельности. Раньше у нас был встроенный в компанию инструмент импорта, который просматривал записи, чтобы загрузить файл с более чем миллионом записей, потребовалось бы 18-20 часов (что не часто случалось, когда он создавался, но во много раз наступление дня сейчас).
Я вижу два варианта: во-первых, использовать массовую вставку для загрузки в промежуточную таблицу и выполнить все необходимые операции по очистке этой таблицы. Как вы определяете, существует ли запись? Вы должны быть в состоянии построить обновление на основе набора, присоединившись к промежуточной таблице в тех полях, которые определяют обновление. Часто я добавлял столбец в свою промежуточную таблицу для идентификатора записи, которой он соответствует, и заполнял ее с помощью запроса, а затем выполнял обновление. Затем вы делаете вставку записей, которые не имеют соответствующего идентификатора. Если у вас слишком много записей, чтобы делать все сразу, вы можете запускать партии (что да, это цикл), но делать партии значительно больше, чем 1 запись за раз (я обычно начинаю с 2000, а затем на основе время, которое требуется для этого определения, могу ли я сделать больше или меньше в партии).
Я думаю, что в 2008 году также есть заявление о слиянии, но у меня еще не было возможности его использовать. Ищите это в книгах онлайн.
Альтернатива - использовать SSIS, оптимизированный по скорости. SSIS - сложная вещь, а кривая обучения крутая.
Один из способов - загрузить CSV-файл в DataTable (или, скорее, в DataReader), а затем выполнить пакетный анализ результатов с помощью SqlBulkCopy -
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
Это довольно эффективно, и вы можете сделать некоторые сопоставления столбцов. Совет. При отображении столбцов с помощью SqlBulkCopy они чувствительны к регистру.
Вам нужно кататься здесь вообще? Можно ли предоставить данные таким образом, чтобы SQL Server мог использовать групповой импорт, чтобы загрузить их, а затем обработать дубликаты в базе данных после завершения импорта?
Когда дело доходит до тяжелой работы с большим количеством данных, мой опыт, как правило, заключается в том, что работа с базой данных в максимально возможной степени намного быстрее и требует меньше ресурсов.
Другой подход заключается в написании хранимой процедуры.Net на сервере на сервере для работы со всем файлом...
Только если вам нужно больше контроля, чем у решения Криса Краузе - я большой поклонник того, чтобы сделать его простым (и многократно используемым) там, где мы можем...