Единственный разумный способ обновить таблицу записей 120M - это инструкция SELECT
, которая заполняет таблицу второй. Вы должны позаботиться об этом. Инструкции ниже.
Простого случай
Для таблицы ж/из кластерного индекса, в то время, ж/из параллельного DML:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- воссоздавать индексы, ограничения и т.д. на новый стол
- переключатель старый и новый w/ALTER SCHEMA ... TRANSFER.
- падение старого стол
Если вы не можете создать клон схемы, другое имя таблицы в той же схеме будет делать. Не забывайте переименовывать все свои ограничения и триггеры (если применимо) после переключения.
Непростое Case
Во-первых, воссоздать ваш 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
Проверьте результаты. Если все кажется в порядке:
- усечь таблицу Clone
- убедитесь, что база данных в насыпью протоколированием или простая модель восстановления
- выполнить полную вставку.
Это займет некоторое время, но не дольше, чем обновление. Как только он завершится, проверьте данные в таблице клонирования, чтобы убедиться, что все правильно.
Затем заново создайте все некластеризованные первичные ключи/уникальные ограничения/индексы и ограничения внешнего ключа (в этом порядке). Восстановите ограничения по умолчанию и проверки, если это применимо. Восстановите все триггеры. Восстановите каждое ограничение, индекс или триггер в отдельной партии. например:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Наконец, переместите dbo.BaseTable
к резервной схеме и clone.BaseTable
к схеме ДБО (или там, где ваш стол должен жить).
-- -- 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 в отдельной таблице. Включите этот триггер перед началом вставки. Затем в той же транзакции, которую вы выполняете для передачи схемы, используйте таблицу журналов для выполнения проверки подлинности. Сначала проверьте это на подмножестве данных! Дельты легко завинчиваются.
Проблема основана на IO. Ремус рассмотрел эту проблему здесь: http://stackoverflow.com/questions/3523831/update-statement-running-for-too-long-or-not/3523903#3523903 –
Я был обеспокоен тем, что это может быть основано на IO. К сожалению, я не могу с этим поделать. Будут ли меньшие инкрементные партии работать быстрее? –
Нет. Общий объем данных будет таким же: обновленные страницы и страницы журнала. Это все еще 120M строк, и эти строки эффективно записываются дважды (один раз в журнал и один раз в хранилище резервных копий). Таким образом, время должно быть пропорционально размеру вашего стола. Если это таблица с одним 4 байтом int, это грубые 1G данных для записи (120 * 4 = 480, * 2 - 960). Итак, насколько велика общая таблица? –