Ответ 1
Единственный нормальный способ обновления таблицы из записей 120M - это оператор SELECT
, который заполняет таблицу второй. Вы должны позаботиться об этом. Инструкции ниже.
Простой случай
Для таблицы без кластеризованного индекса за время без параллельного DML:
-
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- воссоздать индексы, ограничения и т.д. в новой таблице
- переключиться на старый и новый w/ALTER SCHEMA... TRANSFER.
- удалить старую таблицу
Если вы не можете создать схему клонирования, это будет другое имя таблицы в той же схеме. Не забудьте переименовать все ваши ограничения и триггеры (если применимо) после переключения.
Несложный случай
Сначала заново создайте BaseTable
с тем же именем под другой схемой, например clone.BaseTable
. Использование отдельной схемы упростит процесс переименования позже.
- Включить кластеризованный индекс, если это применимо. Помните, что первичные ключи и уникальные ограничения могут быть сгруппированы, но необязательно.
- Включить столбцы идентификации и вычисленные столбцы, если применимо.
- Включите новый столбец INT, где бы он ни находился.
- Не включать любое из следующего:
- Триггеры
- ограничения внешних ключей
- некластеризованные индексы/первичные ключи/уникальные ограничения
- проверить ограничения или ограничения по умолчанию. Значения по умолчанию не имеют большого значения, но мы пытаемся сохранить вещи минимальные.
Затем проверьте свою вставку с 1000 строк:
-- assuming an IDENTITY column in BaseTable
SET IDENTITY_INSERT clone.BaseTable ON
GO
INSERT clone.BaseTable WITH (TABLOCK) (Col1, Col2, Col3)
SELECT TOP 1000 Col1, Col2, Col3 = -1
FROM dbo.BaseTable
GO
SET IDENTITY_INSERT clone.BaseTable OFF
Изучите результаты. Если все выглядит по порядку:
- обрезать таблицу клонов
- убедитесь, что база данных находится в массивной или простой модели восстановления
- выполнить полную вставку.
Это займет некоторое время, но не до тех пор, пока обновление. Как только он завершится, проверьте данные в таблице клонирования, чтобы убедиться, что все правильно.
Затем заново создайте все некластеризованные первичные ключи/уникальные ограничения/индексы и ограничения внешнего ключа (в этом порядке). Восстановите ограничения по умолчанию и проверки, если это применимо. Восстановите все триггеры. Восстановите каждое ограничение, индекс или триггер в отдельной партии. например:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Наконец, переместите dbo.BaseTable
в схему резервного копирования и clone.BaseTable
в схему dbo (или там, где должна находиться ваша таблица).
-- -- perform first true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
-- GO
-- -- create a backup schema, if necessary
-- CREATE SCHEMA backup_20100914
-- GO
BEGIN TRY
BEGIN TRANSACTION
ALTER SCHEMA backup_20100914 TRANSFER dbo.BaseTable
-- -- perform second true-up operation here, if necessary
-- EXEC clone.BaseTable_TrueUp
ALTER SCHEMA dbo TRANSFER clone.BaseTable
COMMIT TRANSACTION
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() -- add more info here if necessary
ROLLBACK TRANSACTION
END CATCH
GO
Если вам нужно освободить место на диске, вы можете сбросить свою исходную таблицу в это время, хотя может быть разумным сохранить ее еще дольше.
Излишне говорить, что это идеальная операция офлайн. Если у вас есть люди, которые изменяют данные во время выполнения этой операции, вам придется выполнить операцию с использованием переключателя схемы. Я рекомендую создать триггер на dbo.BaseTable
, чтобы записать все DML в отдельную таблицу. Включите этот триггер перед началом вставки. Затем в той же транзакции, которую вы выполняете для передачи схемы, используйте таблицу журналов для выполнения проверки подлинности. Сначала проверьте это на подмножестве данных! Дельты легко завинчиваются.