2011-08-23 60 views
6

我有一個擁有〜40 000 000行的數據庫表。我想爲此表添加一個標識列。如何以對數友好的方式做到這一點?如何將標識列添加到具有大量行的現有數據庫表中

當我做到以下幾點:

ALTER TABLE table_1 
    ADD id INT IDENTITY 

這只是填補了整個日誌空間。

有沒有辦法以對數友好的方式做到這一點?該數據庫在SQL Server 2008上。

謝謝, Mohan。

+2

這是MySQL,SQL Server,PostGres,Oracle嗎? – JNK

+7

禁用日誌,添加列,啓用日誌。 –

+0

這不應該是一個答案,而不僅僅是一個評論? –

回答

4

整體過程可能會慢得多,整體鎖定開銷較大,但如果您只關心事務日誌大小,則可以嘗試以下操作。

  1. 添加一個可爲空的整數非標識列(僅限元數據更改)。
  2. 編寫代碼以批量更新此唯一順序整數。這將減少每個單獨事務的大小並保持日誌大小下降(假設簡單的恢復模式)。我的代碼如下分批顯示100,希望你有一個現有的PK,你可以利用它來提取你離開的地方,而不是重複的掃描,這些掃描將會持續到最後。
  3. 使用ALTER TABLE ... ALTER COLUMN將該列標記爲NOT NULL。這將要求整個表被鎖定和掃描以驗證更改,但不需要太多日誌記錄。使用ALTER TABLE ... SWITCH將列設置爲標識列。這是一個僅用於元數據的更改。

示例代碼下面

/*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 ; 
+0

您是否有時間可以將dataqbase置於單用戶模式?最好在單用戶模式下執行此操作,並且除dba外的所有用戶均被鎖定。 – HLGEM

1

我只是這樣做是爲了我的表有2700行。轉到表的設計,添加新列,將其設置爲不允許空值,將列設置爲列屬性中的標識列,並且應該這樣做。我簡直就是在不到5分鐘的時間內完成了這個工作,而且它對我很有幫助。如果這回答你的問題,請選擇答案。

相關問題