2010-10-26 6 views
6

Прежде всего позвольте мне сказать, что я работаю на SQL Server 2005, поэтому у меня нет доступа к MERGE.Удалить All/Bulk Insert

У меня есть таблица с ~ 150 тыс. Строк, которые я ежедневно обновляю из текстового файла. Поскольку строки выпадают из текстового файла, мне нужно удалить их из базы данных, и если они меняются или являются новыми, мне необходимо обновить/вставить соответственно.

После некоторого тестирования я обнаружил, что производительность намного ускоряется, чтобы выполнить полное удаление, а затем объемную вставку из текстового файла, а не читать через строку строки, выполняющую обновление/вставку. Однако недавно я столкнулся с некоторыми сообщениями о том, как имитировать функции MERGE SQL Server 2008, используя временную таблицу и вывод инструкции UPDATE.

Меня заинтересовало это, потому что я изучаю, как я могу исключить время в методе Delete/Bulk Insert, когда таблица не имеет строк. Я все еще думаю, что этот метод будет самым быстрым, поэтому я ищу лучший способ решить проблему с пустой таблицей.

Благодаря

ответ

5

Я думаю, что ваш быстрый метод будет:

  1. отбросьте все внешние ключи и индексы из вашей таблицы.
  2. Truncate ваш стол.
  3. Массовая вставка ваших данных.
  4. Восстановите свои внешние ключи и указатели .
+0

Спасибо за советы, я не знал о Truncate и, скорее всего, буду использовать его, но я пытаюсь устранить короткий промежуток времени между удалением и объемной вставкой, когда таблица пуста. Есть идеи? – rpf3

+0

@ rpf3: Попробуйте TRUNCATE. Я думаю, что это устранит большую часть задержки, о которой вы говорите. –

+0

Truncate был определенно быстрее, чем удаление, но для Bulk Insert все равно требуется ~ 9 секунд. Меня попросили выяснить, есть ли способ устранить даже это небольшое количество времени простоя, потому что другие процессы могут попасть в базу данных во время выполнения. – rpf3

0

Для скорости сырья, я думаю, что с ~ 150 К строк в таблице, я бы просто отбросил таблицу, воссоздал ее с нуля (без индексов), а затем насыпную загрузку заново. После того, как объемная загрузка будет выполнена, создайте индексы.

Это предполагает, что, если период времени, когда таблица пуста/не существует, приемлема, что она звучит так, как это могло бы быть.

3

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

begin tran; 

truncate table stage_table 

bulk insert stage_table 
from N'C:\datafile.txt' 

commit tran; 
+0

Я думал об этом, но если у вас нет прав доступа к файлу данных или файлу формата, возникает ошибка, которая не может быть поймана SQL TRY/CATCH и остановит транзакцию кода mid, оставив ее открытой. – rpf3

1

Альтернативное решение, которое бы satsify ваше требование не иметь «время простоя «для таблицы, которую вы обновляете.

Похоже, что сначала вы читали файл и делали INSERT/UPDATE/DELETE 1 строку за раз.Более производительный подход, чем та, что не включает в себя очистку вниз таблицы выглядит следующим образом:

1) основная масса не загружает файл в новую, отдельную таблицу (без индексов)
2), а затем создать ПК на нем
3) Запустите 3 оператора, чтобы обновить исходную таблицу из этой новой (временной) таблицы:
УДАЛИТЬ строки в основной таблице, которых нет в новой таблице
UPDATE строки в основной таблице, где есть соответствующая строка в новом столе
INSERT строки в основной таблице из новой таблицы, где они еще не существуют

Это будет работать лучше, чем по очереди, и, надеюсь, удовлетворит ваши общие требования

+0

Спасибо, я собираюсь запустить некоторые тесты, чтобы увидеть, хочу ли я использовать это или просто сохранить объемную вставку внутри заблокированной транзакции за короткое время. – rpf3

1

Существует способ обновить таблицу с нулевым временем простоя: сохранить данные за два дня в таблице и удалить старые строки после Загрузка новых!

  1. Добавить столбец DataDate, представляющий дату, для которой допустимы строки ~ 150K.
  2. Создайте однострочную таблицу с одним столбцом с «сегодняшним» DataDate.
  3. Создайте представление двух таблиц, в которых выбираются только строки, соответствующие строке в таблице DataDate. Индексируйте его, если хотите. Теперь читатели обращаются к этому виду, а не к таблице.
  4. Массовая вставка строк. (Очевидно, вам нужно добавить DataDate в каждую строку.)
  5. Обновление таблицы DataDate. Обновления мгновенно!
  6. Удалить вчерашние ряды на досуге.

SELECT производительность не пострадает; объединение одной строки до 150 000 строк по первичному ключу не должно представлять проблем ни на одном сервере, которому меньше 15 лет.

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

Смежные вопросы