Улучшение INSERT INTO - ОТ SELECT, ЗАПРОС S'L

В настоящее время я получил этот тип запроса, генерируемого программной (c)

INSERT INTO TableName (Field1, Field2, Field3)
SELECT Field1, Field2, Field3 FROM TableName2

Проблема в том, что SELECT может иметь результат многих записей (например, миллион), так что это займет много раз, и в результате является тайм-аут соединения.

Кроме того, если я отделяю все вставки в одной вставке (для этого примера, один миллион вставить запросы), это займет очень много времени, чтобы выполнить ... но это работает ...

Есть ли способ улучшить этот тип запроса?

Я использую MSS'l 2005

Thx

Ответ на: "Улучшение INSERT INTO - ОТ SELECT, ЗАПРОС S'L"

Количество ответов:10

Ну, если это полная копия, я задаюсь вопросом, если вы не должны смотреть на объемных инструментов нагрузки?

  • BULK INSERT (TS'L)
  • SqlBulkCopy (.NET)
  • bcp (командная линия)
  • и т.д.

Если бы вы "--32-" было оговорка Where clause, I'd check that it was suitably indexed... , я бы проверить, что она была соответствующим образом ...

Дополнительно:

  • , возможно, падение индексов и триггеров, прежде чем делать INSERT (воссоздать потом)
  • рассмотреть вопрос о снижении всей таблицы и с помощью SELECT INTO ? (см. комментарии)

Установить CommandTimeout property of the свойство SqlCommand you're using to a sensible value (10 minutes or something). Remember that вы используете для разумного значения (10 минут или что-то). Помните, что CommandTimeout is in seconds. находится в секундах.

Я узнал, что, если у вас есть много инструкций INSERT, которые выполняются последовательно, вы можете улучшить производительность, добавив заявление "GO" после каждого xxxx число вставить заявления:

...
INSERT INTO Table ( ... ) VALUES ( ... )
INSERT INTO Table ( ... ) VALUES ( ... )
INSERT INTO Table ( ... ) VALUES ( ... )
GO
INSERT INTO Table ( ... ) VALUES ( ... )
INSERT INTO Table ( ... ) VALUES ( ... )
...

Другая возможность, может быть, это убедиться, что ваш INSERT INTO . SELECT FROM запрос не вставляет все за один раз, вместо этого использовать какую-то технику paging:

INSERT INTO Table ...
SELECT ...
FROM OtherTable WHERE Id > x and Id < y

Вы не указываете, какую проблему вы решаете с помощью этого подхода. Очевидно, где бы сузить рекорд. Но если набор результатов не будет изменен в Новой таблице, то зачем вообще реплицировать данные? Почему бы не запросить непосредственно из Источника?

либо навалом нагрузки с помощью файла, а затем bcp / BULK INSERT или партии его в партии 5K или около того

Во-первых, никогда не пытайтесь вставить миллион записей через C. Никогда не обработайте большие группы записей по одному. Это работа, которая должна быть сделана в базе данных по базе данных. USe навалом вставки или SSIS или DTS, чтобы сделать это. А потом запланировать его как работу в нерабочее время. Если это все еще занимает слишком много времени, то я предлагаю вам запустить его в партии из нескольких тысяч (вам придется играть с собственной базой данных, чтобы увидеть, что лучший выбор, как число, которое вы можете безопасно обрабатывать в значительной степени зависит от таблиц, индексации, как быстро ваш сервер и сколько пользователей также пытаются сделать работу против тех же таблиц.

конец

Не самый эффективный, но он будет работать и должен позволить вам сохранить транзакцию войти вниз. Если вам это нужно также убедитесь, что использовать не блокировки ключевое слово, так что вы не блокировать другие транзакции при выполнении этого большого хода (если вы используете BCP или DTS, поскольку они гораздо быстрее).

Некоторые из того, что было сказано, вероятно, ваш лучший выбор, хотя. Используйте BCP, DTS или другой объемный инструмент. Если вы можете упасть индексы, это сделает вещи идти намного быстрее.

набор @stop (выберите кол (primaryKey) из таблицыНамея, где primaryKey не в destinstiontable)

в то время как (@stop выбрать (...) из sourcetable, где primaryKey не в (выберите primarykey от destinationtable)

коммит

набор @stop (выбрать счет (primaryKey) из tableName, где primaryKey не в destinstiontable) начать транзакцию

вставить в пункт назначенияТебле (...)

Еще один способ, который мы использовали в прошлом, чтобы создать температуру таблицу с основными ключами мы хотим двигаться и использовать в то время как цикл. Таким образом, вы можете сделать это в своего рода блок моды, чтобы избежать крупных транзакций накладных расходов, если вы отменили, и он должен был откатить.

В основном то, что вы в конечном итоге делает это вставка в таблицу (...) выберите (...) выбрать (...) из названия таблицы, где основной ключ в (выбрать верхний 10000 ключ от соблазняемого)

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

Еще один способ будет использовать курсоры, чтобы уменьшить количество записей, которые вы обрабатываете за один раз.

Другой метод цикла было бы сделать что-то вроде этого в то время как цикл.

объявить @stop как int

Некоторые хорошие ответы здесь.

Просто хотел бы добавить, что если у вас есть индексы на таблице назначения они замедлят операцию. Однако восстановление индекса иногда может занять много времени, если вы делаете технику создания капли.

Если вы не хотите, чтобы падение индексов, используйте ORDER BY in your в вашем SELECT that matches the , что соответствует назначения кластерный индекс, это, кажется, поможет (вероятно, помогает свести к минимуму страницы расколов).

Ок, Есть несколько фундаментальных вопросов.

  1. I'O - Вставка в таблицу при чтении из другой таблицы, скорее всего, вызовет спор диска, если таблицы не находятся на отдельных дисках. Положите противоположные таблицы на физически разные шпиндели.

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

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

  4. Расширение файлов - Убедитесь, что у вас есть набор для расширения его файлов на достойной скорости, как 10% или около того. В противном случае ему придется постоянно меняться размером его файлов и нулю из диска. Есть способы, чтобы предотвратить его от необходимости обнуления диска, а также, как включение разрешения Массовый файл операции в вашей группы политики для пользователя службы Sql.

Откровенно говоря, кроме этого и некоторые другие предложения, это весьма маловероятно, вы будете делать вставку с миллионами строк в сделке будет действительно быстро. Если вы сделали это через Bulk Insert, это было бы значительно быстрее, хотя это может быть не то, что вам нужно с точки зрения приложения.

Вы можете улучшить производительность выбора.И вы можете улучшить производительность с помощью таблоков на столе, в который вы входите.

Вы протестировали sql через sql студии управления сервером, чтобы увидеть, сколько времени это на самом деле занимает? Я хотел бы начать там.