Какой самый быстрый способ вставить большое количество строк?

27

У меня есть база данных, в которую я загружаю файлы в промежуточную таблицу, из этой промежуточной таблицы у меня есть 1-2 соединения, чтобы разрешить некоторые внешние ключи, а затем вставить эти строки в итоговую таблицу (которая имеет один раздел в месяц). У меня есть около 3,4 миллиарда строк за три месяца данных.

Какой самый быстрый способ получить эти строки из финальной таблицы? Задача потока данных служб SSIS (которая использует представление в качестве источника и активна быстрая загрузка) или команда Вставить INTO SELECT ....? Я попробовал Задачу потока данных и смог получить около 1 миллиарда строк примерно за 5 часов (8 ядер / 192 ГБ ОЗУ на сервере), что мне кажется очень медленным.

nojetlag
источник
1
Находятся ли разделы в отдельных файловых группах (и находятся ли они на разных физических дисках)?
Аарон Бертран
3
Действительно хороший ресурс Руководство по производительности загрузки данных . Это позволяет оптимизировать производительность, например, включить TF610 , использовать BCP OUT / IN, SSIS и т. Д. Вам просто нужно следовать рекомендациям и протестировать их в своей среде.
Кин Шах
@ Аарон, да, в месяц прилагается одна файловая группа, 12 сан-лунов, так что все джаны идут на один лун и т. Д. Не знаю, сколько дисков за лун, но должно быть много.
nojetlag
Да, я действительно имел в виду «наборы дисков» и, вероятно, мог бы также упомянуть контроллеры, которые могут быть насыщенными.
Аарон Бертран
@Kin взглянул на руководство, но оно устарело: «Назначение SQL Server - это самый быстрый способ массовой загрузки данных из потока данных служб Integration Services в SQL Server. Это назначение поддерживает все параметры массовой загрузки SQL Server - кроме ROWS_PER_BATCH «. и в SSIS 2012 они рекомендуют назначение OLE DB для повышения производительности.
nojetlag

Ответы:

25

Один общий подход:

  1. Отключить / удалить индексы / ограничения на целевой таблице.
  2. INSERT dbo.[Target] WITH (TABLOCKX) SELECT ...
  3. Конечно, благодаря кредитам JNK вы можете выполнять описанные выше действия в пакетах nстрок, что может снизить нагрузку на журнал транзакций и, конечно же, означает, что в случае сбоя какого-либо пакета вам потребуется только запустить этот пакет. Я писал об этом в блоге (хотя в отношении удалений применяются те же основные понятия) здесь: http://www.sqlperformance.com/2013/03/io-subsystem/chunk-deletes
  4. Повторно включите / заново создайте индексы / ограничения для целевой таблицы (и, возможно, вы можете отложить некоторые из них, если они не нужны для всех операций, и более важно быстро получить базовые данные в оперативном режиме).

Если ваши разделы являются физическими, а не просто логическими, вы можете выиграть некоторое время, если разные процессы будут заполнять разные разделы одновременно (конечно, это означает, что вы не можете использовать TABLOCK/ TABLOCKX). Это предполагает, что источник также подходит для нескольких процессов, выбирающих без перекрытия / блокировки и т. Д., И делает эту сторону операции еще более медленной (подсказка: создайте кластеризованный индекс на источнике, который соответствует схеме разделения на месте назначения).

Вы также можете рассмотреть что-то более примитивное, например BCP OUT/BCP IN .

Я не знаю, что я прыгнул бы в SSIS, чтобы помочь с этим. Там, вероятно, есть некоторые преимущества, но я не знаю, что усилия оправдывают экономию.

Аарон Бертран
источник
2
Не отбрасывайте слепо индексы (особенно кластерный индекс), если ваши данные не отсортированы. Удаление индекса и ожидание воссоздания кластерного индекса может быть огромной ошибкой, поскольку это может стоить как огромного дискового пространства, так и огромного количества времени. Я не первый, кто испытал такую ​​ошибку. Посмотрите на описание «План Б» в этой статье sqlmag.com/t-sql/… . У автора была такая же проблема.
Цзяо
10

Глядя на вашу проблему с точки зрения SSIS, я чувствую, что это заняло так много времени, потому что у вас не было партии. Это может привести к слишком большому количеству строк, заполняющих конвейер служб SSIS, и в результате может снизить производительность SSIS. То, что вам нужно сделать, это изменить параметры строк в пакете и, возможно, максимальный размер вставки. Теперь, что вы также установите, будет зависеть от объема памяти, доступной вашему серверу SSIS? Какова скорость диска вашего экземпляра SQL Server? Лучший способ сделать это - проверить. Давайте, например, использовать 10 000. Это отправит пакет на сервер 10000 за раз, таким образом, предотвращая переполнение конвейера, и поможет ускорить этот процесс. Эти настройки установлены в вашем месте назначения OLEDB.

OLEDB Направление

Если это проблема, вы также можете добавить задачу «Выполнить SQL» до и после выполнения, как это предлагает @AaronBertrand, и удалить / повторно добавить любые индексы или ограничения в таблицу.

Зейн
источник
1
Есть отличный вопрос о том, что означает «быстрая загрузка» в других местах на DBA.SE: dba.stackexchange.com/questions/141430/… .
Джон на все