Медленная массовая вставка для таблицы со многими индексами - PullRequest
26 голосов
/ 15 апреля 2009

Я пытаюсь вставить миллионы записей в таблицу с более чем 20 индексами.

В последнем запуске потребовалось более 4 часов на 100 000 строк, и запрос был отменен через 3½ дня ...

Есть ли у вас какие-либо предложения о том, как ускорить это.

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

Дополнительная информация:

  • Пространство, используемое индексами, примерно в 4 раза больше пространства, используемого одними данными
  • Вставки заключены в транзакцию на 100 000 строк.

Обновление статуса:

Принятый ответ помог мне сделать это намного быстрее.

Ответы [ 4 ]

42 голосов
/ 15 апреля 2009

Вы можете отключить и включить индексы. Обратите внимание, что их отключение может иметь нежелательные побочные эффекты (например, наличие дублированных первичных ключей или уникальных индексов и т. Д.), Которые будут обнаружены только при повторном включении индексов.

--Disable Index
ALTER INDEX [IXYourIndex] ON YourTable DISABLE
GO

--Enable Index
ALTER INDEX [IXYourIndex] ON YourTable REBUILD
GO
7 голосов
/ 15 апреля 2009

Это звучит как операция хранилища данных. Было бы нормально удалить индексы перед вставкой и перестроить их потом.

Когда вы перестраиваете индексы, сначала строите кластеризованный индекс, и наоборот, отбрасывайте его последним. Все они должны иметь коэффициент заполнения 100%.

Код должен быть примерно таким

if object_id('Index') is not null drop table IndexList
select name into Index from dbo.sysindexes where id = object_id('Fact')

if exists (select name from Index where name = 'id1') drop index Fact.id1
if exists (select name from Index where name = 'id2') drop index Fact.id2        
if exists (select name from Index where name = 'id3') drop index Fact.id3
.
.
BIG INSERT

RECREATE THE INDEXES
4 голосов
/ 15 апреля 2009

Как отмечается в другом ответе, отключение индексов будет очень хорошим началом.

4 часа на 100 000 строк [...] Вставки заключаются в транзакцию на 100 000 строк.

Вы должны обратить внимание на уменьшение числа, сервер должен поддерживать огромное количество состояний во время транзакции (чтобы его можно было откатить), это (наряду с индексами) означает, что добавление данных - очень тяжелая работа. 1007 *

Почему бы не обернуть каждый оператор вставки в свою собственную транзакцию?

Также рассмотрите природу SQL, который вы используете, добавляете ли вы по одной строке на оператор (и в оба конца) или добавляете много?

3 голосов
/ 09 октября 2011

В этих случаях часто предлагается отключить, а затем снова включить индексы. У меня есть сомнения относительно этого подхода, потому что:

(1) Пользователю БД приложения необходимы права на изменение схемы, которыми оно обычно не должно обладать. (2) Выбранный подход вставки и / или схема индекса могут быть в первую очередь менее оптимальными, в противном случае перестройка полных деревьев индекса не должна выполняться быстрее, чем приличная пакетная вставка (например, клиент выдает один оператор вставки за раз, что приводит к тысячи обращений к серверу или плохой выбор кластерного индекса, что приводит к постоянному разделению узла индекса).

Вот почему мои предложения выглядят немного иначе:

  • Увеличение размера пакета ADO.NET
  • Мудро выбирайте кластеризованный индекс целевой таблицы, чтобы вставки не приводили к расщеплению узлов кластерного индекса. Обычно столбец идентификаторов является хорошим выбором
  • Пусть клиент сначала вставит во временную таблицу кучи (таблицы кучи не имеют кластеризованного индекса); затем выполните один большой оператор "вставка в выбор", чтобы поместить все эти данные промежуточной таблицы в фактическую целевую таблицу
  • Apply SqlBulkCopy
  • Уменьшите журнал транзакций, выбрав модель восстановления с массовой регистрацией

Более подробную информацию вы можете найти в этой статье .

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