Det enda vettiga sättet att uppdatera en tabell med 120 miljoner poster är med en SELECT
uttalande som fyller en sekund tabell. Du måste vara försiktig när du gör detta. Instruktioner nedan.
Enkelt fall
För en tabell utan ett klustrat index, under en tid utan samtidig DML:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- återskapa index, begränsningar, etc på ny tabell
- byt gammalt och nytt med ALTER SCHEMA ... ÖVERFÖRING.
- släpp gammal tabell
Om du inte kan skapa ett klonschema, fungerar ett annat tabellnamn i samma schema. Kom ihåg att byta namn på alla dina begränsningar och utlösare (om tillämpligt) efter bytet.
Icke-enkelt fall
Återskapa först din BaseTable
med samma namn under ett annat schema, t.ex. clone.BaseTable
. Om du använder ett separat schema förenklas byteprocessen senare.
- Inkludera det klustrade indexet , om tillämpligt. Kom ihåg att primärnycklar och unika begränsningar kan vara klustrade, men inte nödvändigtvis.
- Inkludera identitetskolumner och beräknade kolumner , om tillämpligt.
- Inkludera din nya INT-kolumn , var den än hör hemma.
- Inkludera inte något av följande:
- utlösare
- restriktioner för främmande nyckel
- icke-klustrade index/primära nycklar/unika begränsningar
- kontrollera begränsningar eller standardbegränsningar. Standardinställningar gör inte så stor skillnad, men vi försöker hålla saker och ting minimala.
Testa sedan din infogning med 1000 rader:
-- 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
Undersök resultaten. Om allt visas i ordning:
- trunkera klontabellen
- se till att databasen är inloggad i bulk eller enkel återställningsmodell
- utför hela infogningen.
Detta kommer att ta ett tag, men inte alls lika länge som en uppdatering. När det är klart, kontrollera data i klontabellen för att se till att allt är korrekt.
Återskapa sedan alla icke-klustrade primärnycklar/unika begränsningar/index och främmande nyckelbegränsningar (i den ordningen). Återskapa standard och kontrollera begränsningar, om tillämpligt. Återskapa alla triggers. Återskapa varje begränsning, index eller trigger i en separat batch. t.ex.:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Flytta slutligen dbo.BaseTable
till ett backupschema och clone.BaseTable
till dbo-schemat (eller varhelst din tabell är tänkt att bo).
-- -- 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
Om du behöver frigöra diskutrymme kan du släppa din ursprungliga tabell nu, även om det kan vara klokt att behålla det ett tag till.
Det behöver inte sägas att detta är idealiskt offline drift. Om du har personer som ändrar data medan du utför den här operationen måste du utföra en sanningsoperation med schemaväxeln. Jag rekommenderar att du skapar en utlösare på dbo.BaseTable
för att logga all DML till en separat tabell. Aktivera denna utlösare innan du startar infogningen. Sedan använder du loggtabellen i samma transaktion som du utför schemaöverföringen för att utföra en sanning. Testa detta först på en delmängd av data! Deltas är lätta att skruva upp.