Ogólny proces będzie prawdopodobnie dużo wolniejszy, z większym ogólnym obciążeniem blokowania, ale jeśli zależy Ci tylko na rozmiarze dziennika transakcji, spróbuj wykonać następujące czynności.
- Dodaj kolumnę z zerową liczbą całkowitą bez tożsamości (zmiana tylko metadanych).
- Wpisz kod, aby zaktualizować tę wartość, używając unikatowych ciągłych liczb całkowitych w pakietach. Zmniejszy to rozmiar każdej pojedynczej transakcji i zmniejszy rozmiar dziennika (zakładając prosty model odzyskiwania). Mój kod poniżej robi to w partiach po 100, mam nadzieję, że masz istniejący PK, który możesz wykorzystać do pobrania w miejscu, w którym przerwałeś, zamiast powtarzających się skanów, które pod koniec będą coraz dłuższe.
- użyj
ALTER TABLE ... ALTER COLUMN
, aby oznaczyć kolumnę jako NOT NULL
. Będzie to wymagało zablokowania i zeskanowania całej tabeli w celu zatwierdzenia zmiany, ale nie będzie wymagać dużej ilości rejestrowania.
- Użyj kolumny
ALTER TABLE ... SWITCH
, aby kolumna stała się kolumną tożsamości. Jest to zmiana tylko metadanych.
Przykład kodu poniżej
/*Set up test table with just one column*/
CREATE TABLE table_1 (original_column INT)
INSERT INTO table_1
SELECT DISTINCT
number
FROM master..spt_values
/*Step 1 */
ALTER TABLE table_1 ADD id INT NULL
/*Step 2 */
DECLARE @Counter INT = 0 ,
@PrevCounter INT = -1
WHILE @PrevCounter <> @Counter
BEGIN
SET @PrevCounter = @Counter;
WITH T AS (SELECT TOP 100
* ,
ROW_NUMBER() OVER (ORDER BY @@SPID)
+ @Counter AS new_id
FROM table_1
WHERE id IS NULL
)
UPDATE T
SET id = new_id
SET @Counter = @Counter + @@ROWCOUNT
END
BEGIN TRY;
BEGIN TRANSACTION ;
/*Step 3 */
ALTER TABLE table_1 ALTER COLUMN id INT NOT NULL
/*Step 4 */
DECLARE @TableScript NVARCHAR(MAX) = '
CREATE TABLE dbo.Destination(
original_column INT,
id INT IDENTITY(' + CAST(@Counter + 1 AS VARCHAR) + ',1)
)
ALTER TABLE dbo.table_1 SWITCH TO dbo.Destination;
'
EXEC(@TableScript)
DROP TABLE table_1 ;
EXECUTE sp_rename N'dbo.Destination', N'table_1', 'OBJECT' ;
COMMIT TRANSACTION ;
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION ;
PRINT ERROR_MESSAGE() ;
END CATCH ;
Czy to jest MySQL, SQL Server, PostGres, Oracle? – JNK
wyłącz dziennik, dodaj kolumnę, włącz rejestr. –
Czy nie powinna to być odpowiedź, a nie tylko komentarz? –