Эффективная передача большого количества (84 миллиона строк) данных

11

У меня около 84 миллионов строк. Из них все они должны быть перенесены в отдельную базу данных на одном сервере, затем я удаляю, чтобы удалить около 60 миллионов строк из исходной базы данных.

84 миллиона строк находятся в одной таблице. Одна только эта таблица составляет 90% всей базы данных.

Итак ... Источник: 84 миллиона строк -> 24 миллиона строк Назначение: 0 строк -> 84 миллиона строк

Источник работает в режиме полного восстановления, пункт назначения будет работать просто.

Мне интересно, что было бы наиболее эффективным способом сделать это?

План А:

1) ВСТАВИТЬ В НАЗНАЧЕНИЕ ВЫБРАТЬ * ОТ источника

2) источник TRUNCATE

3) INSERT INTO source SELECT * FROM destination WHERE keep_condition = 1

План B:

1) Восстановите резервную копию исходной базы данных в качестве целевой базы данных.

2) Удалите все таблицы, кроме той, которая нужна в целевой базе данных.

3) источник TRUNCATE

4) INSERT INTO source SELECT * FROM destination WHERE keep_condition = 1

План C:

1) ВСТАВИТЬ В НАЗНАЧЕНИЕ ВЫБРАТЬ * ОТ источника

2) УДАЛИТЬ источник, ГДЕ keep_condition = 0

или что-то другое?

Спасибо

elty123
источник
почему вы не используете мастер импорта и экспорта данных? это инструмент, предоставляемый с установкой SQL Server.
Хани Эль Муаллем
Можно ли скопировать 24 млн строк в новую таблицу, а затем просто переименовать две по мере необходимости, чтобы вы не перемещали 84 миллиона строк без необходимости?
LowlyDBA
Это одноразовый или продолжающийся процесс? Я спрашиваю, потому что, учитывая время, которое потребуется для обработки 80M строк, вполне вероятно, что произойдут изменения данных в строках SOURCE, которые должны теперь жить в DESTINATION.
Майкл Грин,
Это выглядит как проблема XY: вам нужно в итоге все 84 мм строки в одной БД и 24 мм строки во второй БД. Какое бизнес-требование требует перемещения 84 мм и удаления 60 мм вместо просто перемещения 24 мм? ссылка: meta.stackexchange.com/questions/66377/what-is-the-xy-problem )
Питер Гиркенс,
У меня очень похожая проблема, и это явно не XY. До распространения законов, касающихся хранения записей, мы хранили все данные. Теперь мы должны удалить строки старше даты, которую мы юридически обязаны хранить. Это означает архивирование и удаление данных за 20 лет, потому что срок юридического хранения в большинстве случаев составляет 7 лет. Я не думаю, что я один, полагая, что Microsoft упущена в том, что не предоставляет функциональность «массового копирования» хранимым процедурам. Приложение не должно быть быстрее при перемещении данных «внутри» БД, чем сама БД. В следующем году еще один год должен быть заархивирован.
Белавский

Ответы:

11

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

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

Спасибо

Эрик Дарлинг
источник
3

«Эффективный» может применяться к использованию файла журнала, производительности ввода-вывода, времени процессора или времени выполнения.

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

CREATE TABLE #temp;
ALTER source -> BULK_LOGGED recovery model

BEGIN TRANSACTION;

    INSERT INTO dest SELECT FROM source;
    INSERT INTO #temp SELECT FROM source WHERE keep_condition=1;
    TRUNCATE TABLE source;
    INSERT INTO source SELECT FROM #temp;

COMMIT TRANSACTION;

ALTER source -> FULL recovery model
DROP TABLE #temp;

Для выполнения операции с минимальным протоколированием должно быть выполнено несколько условий, включая отсутствие резервных копий, работающих в данный момент, базу данных, установленную в BULK_LOGGEDрежим восстановления, и, в зависимости от ваших индексов, таблица назначения может быть пустой. Некоторые из этих действий также изменились (улучшены) с SQL Server 2005 на 2008.

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

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

.. и посмотрим, что работает лучше всего.

РЕДАКТИРОВАТЬ : при выполнении операций с массовой регистрацией убедитесь, что вы делаете резервную копию (полный или журнал транзакций) до и после операции, если вам требуется возможность восстановления на определенный момент времени, и вы подозреваете, что в базе данных могут выполняться другие действия на в то же время, когда ваша работа ETL выполняется.

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

Даниэль Хутмахер
источник
+1 за совет OP, чтобы проверить, какие из них работают лучше. Конечно, это может быть немного трудно получить реальные числа, если у него (ов) нет дублирующейся системы в dev и т. Д.
Макс Вернон,
Просто вопрос: что произойдет, если вы попытаетесь выполнить восстановление на определенный момент времени, когда база данных находилась в режиме массовой регистрации? Я предположил, что любая транзакция, которая не квалифицируется как «основная», будет подлежать восстановлению.
elty123
1
@ elty123 При массовом восстановлении журнала вы можете восстановить только до последней резервной копии журнала. Там нет момента времени восстановления, как было бы с полным восстановлением. Обычно вы переключаетесь на массовое восстановление в журнале, запускаете какой-либо процесс ETL, переключаетесь обратно на полный и затем делаете резервную копию журнала.
RubberChickenLeader
@WindRaven Это не правильно - смотрите мой ответ ниже.
wBob
1
@wBob и @WindRaven, я обновил свой ответ, чтобы отразить необходимость делать резервные копии до и после использования BULK_LOGGEDрежима. Спасибо!
Даниэль Хутмахер,
1

Почему не BCP?

  1. Резервное копирование источника
  2. Изменить sourcedb на массовую регистрацию
  3. Открыть командную строку

  4. bcp server.sourcedb.table out Filename.flt -T -c

  5. bcp "SELECT * FROM sourcedb.table WHERE keep_condition = 1" queryout Filename2.flt -T -c

  6. bcp Server.destinationdb.table in Filename.flt -T -c -b1000

  7. проверить данные

  8. Из SSMS Обрезать исходную таблицу
  9. bcp server.sourcedb.table in Filename2.flt -T -c -b1000
  10. Заменить sourcedb обратно на полный
stacylaray
источник
2
Потому что они на одном сервере. Запись в файловую систему будет дорогой. Лучше создать базу данных и запаковать ее, надеясь воспользоваться моментальной инициализацией файла. Это был бы разумный выбор для баз данных на разных серверах, хотя SSIS был бы моим первым выбором, если он доступен. Примечание: опция -n (нативная) более компактна и безопасна для перемещения данных с SQL Server на SQL Server. Опция -b не влияет на bcp out.
wBob
0

Не думайте, что вам следует рекомендовать изменить модель восстановления без полного резервного копирования базы данных или резервного копирования t-log до и после . Одна из особенностей модели восстановления BULK_LOGGED заключается в том, что вы потеряете возможность выполнять восстановление на определенный момент времени для t-журналов, содержащих операции с массовой регистрацией. Классический сценарий: еженедельное полное резервное копирование, ежечасные резервные копии t-log. Вы изменяете модель восстановления для массовой регистрации и запускаете свою работу. Что-то идет не так, и транзакция откатывается (или вы еще не использовали). Однако вы не уверены, что еще происходило в базе данных, поэтому вы хотите восстановить до известного хорошего момента.

Когда вы можете восстановить? Последнее ежечасное резервное копирование t-log, которое не содержит операций с массовой регистрацией, что может привести к потере n минут транзакций. Полная резервная копия или резервная копия t-журнала перед изменением модели восстановления создаст резервную точку. Какой из них вы выберете, зависит от вашего RTO.

wBob
источник
0

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

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

Майкл Грин
источник