De enige verstandige manier om een tabel met 120 miljoen records bij te werken is met een SELECT
statement dat een seconde . invult tafel. Je moet voorzichtig zijn wanneer je dit doet. Instructies hieronder.
Eenvoudig geval
Voor een tabel zonder een geclusterde index, gedurende een tijd zonder gelijktijdige DML:
SELECT *, new_col = 1 INTO clone.BaseTable FROM dbo.BaseTable
- maak indexen, beperkingen, enz. opnieuw in een nieuwe tabel
- wissel oud en nieuw met ALTER SCHEMA ... OVERDRACHT.
- laat oude tafel vallen
Als u geen kloonschema kunt maken, is een andere tabelnaam in hetzelfde schema voldoende. Vergeet niet om al uw beperkingen en triggers (indien van toepassing) na de overstap te hernoemen.
Niet-eenvoudig geval
Maak eerst uw BaseTable
. opnieuw met dezelfde naam onder een ander schema, bijv. clone.BaseTable
. Het gebruik van een apart schema zal het hernoemen later vereenvoudigen.
- De geclusterde index opnemen , indien toepasselijk. Onthoud dat primaire sleutels en unieke beperkingen geclusterd kunnen zijn, maar niet noodzakelijkerwijs.
- Identiteitskolommen en berekende kolommen opnemen , indien van toepassing.
- Voeg je nieuwe INT-kolom toe , waar het ook hoort.
- Niet opnemen een van de volgende:
- triggers
- buitenlandse belangrijke beperkingen
- niet-geclusterde indexen/primaire sleutels/unieke beperkingen
- controleer beperkingen of standaardbeperkingen. Standaardinstellingen maken niet veel uit, maar we proberen het minimaal te houden.
Test vervolgens uw invoeging met 1000 rijen:
-- 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
Onderzoek de resultaten. Als alles in orde wordt weergegeven:
- kort de kloontabel af
- zorg ervoor dat de database in bulk-gelogd of eenvoudig herstelmodel is
- voer de volledige invoeging uit.
Dit duurt even, maar lang niet zo lang als een update. Zodra het is voltooid, controleert u de gegevens in de kloontabel om er zeker van te zijn dat alles correct is.
Maak vervolgens alle niet-geclusterde primaire sleutels/unieke beperkingen/indexen en externe sleutelbeperkingen opnieuw (in die volgorde). Stel de standaard opnieuw in en controleer de beperkingen, indien van toepassing. Maak alle triggers opnieuw. Maak elke beperking, index of trigger opnieuw in een afzonderlijke batch. bijv.:
ALTER TABLE clone.BaseTable ADD CONSTRAINT UQ_BaseTable UNIQUE (Col2)
GO
-- next constraint/index/trigger definition here
Verplaats tot slot dbo.BaseTable
naar een back-upschema en clone.BaseTable
naar het dbo-schema (of waar uw tabel hoort te leven).
-- -- 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
Als u schijfruimte moet vrijmaken, kunt u op dit moment uw oorspronkelijke tabel laten vallen, hoewel het verstandig kan zijn om deze nog een tijdje te bewaren.
Onnodig te zeggen dat dit idealiter een offline . is operatie. Als mensen gegevens wijzigen terwijl u deze bewerking uitvoert, moet u een true-upbewerking uitvoeren met de schema-switch. Ik raad aan om een trigger te maken op dbo.BaseTable
om alle DML in een aparte tabel te loggen. Schakel deze trigger in voordat u het invoegen start. Gebruik vervolgens in dezelfde transactie waarin u de schemaoverdracht uitvoert de logtabel om een true-up uit te voeren. Test dit eerst op een deel van de data! Delta's zijn gemakkelijk te verknoeien.