2011-08-23 20 views
6

~ 40 000 000 satırı olan bir veritabanı tablom var. Bu tabloya bir kimlik sütunu eklemek istiyorum. Günlük dostu bir şekilde nasıl yapılır?Varolan bir veritabanı tablosuna çok sayıda satır içeren bir kimlik sütunu nasıl eklenir

aşağıdaki yaptığınızda:

ALTER TABLE table_1 
    ADD id INT IDENTITY 

bu sadece tüm günlük alanı doldurur.

Bunu günlük olarak yapmanın bir yolu var mı? Veritabanı SQL Server 2008 üzerinde.

Teşekkürler, Mohan.

+2

Bu MySQL, SQL Server, PostGres, Oracle mı? – JNK

+7

günlüğü devre dışı bırak, sütun ekle, etkinleştirme günlüğü. –

+0

Bu bir cevap değil, sadece bir yorum değil midir? –

cevap

4

Genel işlem muhtemelen daha fazla genel kilitleme yüküyle çok daha yavaş olacaktır, ancak yalnızca işlem günlüğü boyutunu önemsiyorsanız aşağıdakileri deneyebilirsiniz.

  1. Kimliği olmayan tamsayı olmayan bir tamsayı sütunu ekleyin (yalnızca meta verilerde değişiklik).
  2. Bu işlemi, toplu işlerde benzersiz sıralı tam sayılarla güncellemek için kod yazın. Bu, her bir işlemin boyutunu azaltacaktır ve günlük boyutunu düşürecektir (basit kurtarma modeli varsayılarak). Aşağıda yer alan kodum, 100'lük partiler halinde, umarız uzun bir süredir sona erecek olan tekrarlanan taramalardan ziyade bıraktığınız yerden almak için kullanabileceğiniz mevcut bir PK'nize sahip olduğunuzu umar.
  3. Sütunu NOT NULL olarak işaretlemek için ALTER TABLE ... ALTER COLUMN kullanın. Bu, değişikliğin doğrulanması için çok sayıda günlüğe gerek duyulmadan tüm tablonun kilitlenmesini ve taranmasını gerektirir.
  4. Sütunu bir kimlik sütunu yapmak için ALTER TABLE ... SWITCH kullanın. Bu bir meta veri sadece değişikliktir.

Örnek Kod Aşağıda

/*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'i tek kullanıcı moduna geçirebileceğiniz zaman diliminiz var mı? Bunu, tek kullanıcı modunda ve dba kilitli dışında tüm kullanıcılarda prod olarak yapmak en iyisidir. – HLGEM

1

Sadece 2700 satırlar vardır benim tabloya bunu yaptı. Tablonun tasarımına gidin, yeni sütunu ekleyin, boş değerlere izin vermeyecek şekilde ayarlayın, sütunu sütun özelliklerinde bir kimlik sütunu olarak ayarlayın ve bunu yapmalıdır. Tam anlamıyla bunu 5 dakikadan az önce yaptım ve benim için çalıştı. Bu, sorunuza cevap verirse lütfen cevap olarak seçin.

İlgili konular