Единственият разумен начин за актуализиране на таблица от 120M записа е с SELECT
изявление, което попълва секунда маса. Трябва да внимавате, когато правите това. Инструкции по-долу.
Прост случай
За таблица без клъстериран индекс, по време на време без едновременен DML:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- пресъздаване на индекси, ограничения и т.н. в нова таблица
- превключване на старо и ново с ПРОМЕНЯНЕ НА СХЕМАТА ... ПРЕХВЪРЛЯНЕ.
- пуснете старата маса
Ако не можете да създадете клонирана схема, друго име на таблица в същата схема ще свърши работа. Не забравяйте да преименувате всичките си ограничения и задействания (ако е приложимо) след превключвателя.
Непрост калъф
Първо, създайте отново вашата 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 в отделна таблица. Активирайте този тригер, преди да започнете вмъкването. След това в същата транзакция, в която извършвате прехвърлянето на схема, използвайте таблицата на журнала, за да извършите проверка. Тествайте това първо върху подмножество от данни! Делтите са лесни за прецакане.