Единственный разумный способ обновить таблицу из 120M записей - это оператор SELECT
, который заполняет таблицу second .Вы должны заботиться, делая это.Инструкции ниже.
Простой случай
Для таблицы без кластеризованного индекса в течение времени без одновременного DML:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- воссоздание индексов, ограничений и т. Д. Для новой таблицы
- переключение старых и новых с 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 в отдельную таблицу.Включите этот триггер, прежде чем начать вставку.Затем в той же транзакции, в которой вы выполняете передачу схемы, используйте таблицу журнала для выполнения проверки.Проверьте это сначала на подмножестве данных!Дельты легко испортить.