2011-08-23 12 views
6

मेरे पास डेटाबेस तालिका है जिसमें ~ 40 000 000 पंक्तियां हैं। मैं इस तालिका में एक पहचान कॉलम जोड़ना चाहता हूं। लॉग-फ्रेंडली तरीके से इसे कैसे करें?किसी मौजूदा डेटाबेस तालिका में पहचान कॉलम जोड़ने के लिए जिसमें बड़ी संख्या में पंक्तियां

मैं निम्न कार्य करें:

ALTER TABLE table_1 
    ADD id INT IDENTITY 

यह सिर्फ संपूर्ण लॉग अंतरिक्ष को भरती है।

क्या यह लॉग-फ्रेंडली तरीके से ऐसा करने का कोई तरीका है? डेटाबेस SQL ​​सर्वर 2008 पर है।

धन्यवाद, मोहन।

+2

क्या यह MySQL, SQL सर्वर, पोस्टग्रेस, ओरेकल है? – JNK

+7

अक्षम लॉग, कॉलम जोड़ें, लॉग सक्षम करें। –

+0

क्या यह एक उत्तर नहीं होना चाहिए बल्कि सिर्फ एक टिप्पणी नहीं? –

उत्तर

4

समग्र प्रक्रिया अधिक समग्र लॉकिंग ओवरहेड के साथ बहुत धीमी हो जाएगी लेकिन यदि आप केवल लेनदेन लॉग आकार की परवाह करते हैं तो आप निम्न कोशिश कर सकते हैं।

  1. एक निरर्थक पूर्णांक गैर पहचान कॉलम जोड़ें (मेटाडाटा केवल परिवर्तन)।
  2. बैचों में अद्वितीय अनुक्रमिक पूर्णांक के साथ इसे अद्यतन करने के लिए कोड लिखें। यह प्रत्येक व्यक्तिगत लेनदेन के आकार को कम करेगा और लॉग आकार को नीचे रखेगा (सरल वसूली मॉडल मानते हुए)। नीचे मेरा कोड 100 के बैचों में यह उम्मीद करता है कि आपके पास एक मौजूदा पीके है, जिसे आप बार-बार स्कैन करने के बजाय छोड़ने के लिए लीवरेज कर सकते हैं जो अंत में तेजी से लंबा लगेगा।
  3. कॉलम को NOT NULL के रूप में चिह्नित करने के लिए ALTER TABLE ... ALTER COLUMN का उपयोग करें। इस बदलाव को सत्यापित करने के लिए पूरी तालिका को लॉक और स्कैन करने की आवश्यकता होगी लेकिन अधिक लॉगिंग की आवश्यकता नहीं है। कॉलम को पहचान कॉलम बनाने के लिए
  4. कॉलम बनाने के लिए 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

क्या आपके पास टाइमफ्रेम है जब आप डेटाकबेस को एकल उपयोगकर्ता मोड में डाल सकते हैं? एकल उपयोगकर्ता मोड में प्रोड पर और डीबीए को छोड़कर सभी उपयोगकर्ताओं के साथ यह करना सबसे अच्छा है। – HLGEM

1

वहाँ मौजूद डेटा के साथ एक मेज पर एक पहचान स्तंभ जोड़ने के दो तरीके हैं:

  1. पहचान के साथ एक नया टेबल बनाएं, इस के लिए डेटा की प्रतिलिपि नई तालिका तब अस्थायी तालिका का नाम बदलकर मौजूदा तालिका को छोड़ दें।

  2. पहचान के साथ एक नया कॉलम बनाएं & मौजूदा स्तंभ ड्रॉप

संदर्भ: http://cavemansblog.wordpress.com/2009/04/02/sql-how-to-add-an-identity-column-to-a-table-with-data/

1

मैं सिर्फ अपनी मेज 2700 से अधिक पंक्तियां हैं कि करने के लिए ऐसा किया। तालिका के डिज़ाइन पर जाएं, नया कॉलम जोड़ें, इसे नल की अनुमति न दें, कॉलम गुणों में कॉलम को पहचान कॉलम के रूप में सेट करें, और इसे करना चाहिए। मैंने सचमुच सिर्फ 5 मिनट पहले यह किया और यह मेरे लिए काम किया। अगर यह आपके प्रश्न का उत्तर देता है तो कृपया उत्तर के रूप में चुनें।

संबंधित मुद्दे