2009-07-20 13 views
10

मैं एक तालिका से एक फ़ील्ड को बदलना चाहता हूं जिसमें लगभग 4 मिलियन रिकॉर्ड हैं। मैं यह सुनिश्चित किया कि इन क्षेत्रों सभी मान शून्य नहीं हैं और इस क्षेत्र के लिए शून्य नहींSQL सर्वर ALTER फ़ील्ड न्यूल हमेशा के लिए लेता है

ALTER TABLE dbo.MyTable 
ALTER COLUMN myColumn int NOT NULL 

को बदलने के लिए चाहते हैं ... हमेशा के लिए लेने के लिए इस अद्यतन करने के लिए लगता है। इसे गति देने के किसी भी तरीके या मैं ऑफ-घंटों के दौरान इसे रातोंरात कर रहा हूं?

यह भी एक टेबल लॉक का कारण बन सकता है?

+1

व्यक्तिगत तौर पर मैं बंद पीक आवर्स को छोड़कर किसी भी समय एक मौजूदा बड़े तालिका में तालिका संरचना में परिवर्तन करते हैं कभी नहीं होगा।यहां तक ​​कि यदि यह काफी तेज़ है, तो यह उपयोगकर्ताओं को उस क्षण में काम करने की प्रक्रिया में कर सकता है जिससे आप समस्याएं बदल सकते हैं। कोई भी बड़ा परिवर्तन एकल उपयोगकर्ता मोड में भी किया जाता है। जब उपयोगकर्ता कुछ भी नहीं कर पा रहे हैं तो दुखी उपयोगकर्ताओं के मुकाबले दुखी उपयोगकर्ताओं के मुकाबले कुछ भी नहीं कर सकता है (पाठ्यक्रम के पहले और बिना चोटी के घंटों के दौरान) कुछ भी नहीं कर सकता है। – HLGEM

+0

क्या आप जिस कॉलम को बदल रहे हैं वह एफके बाधाओं में शामिल है? – onupdatecascade

+1

प्रोफाइलर में एक त्वरित परीक्षण से यह तालिका पर 'एसएच-एम' लॉक लेता है [जो मूल रूप से सब कुछ के साथ असंगत है] (http://msdn.microsoft.com/en-us/library/ms186396.aspx)। इसके बाद यह निर्धारित करने के लिए कि प्रत्येक पंक्तियां मान्य हैं, प्रत्येक पृष्ठ को पढ़ना होगा। –

उत्तर

4

आप एक फ़ील्ड बदल सकते हैं और इसे फ़ील्ड की जांच किए बिना शून्य नहीं बना सकते हैं। यदि आप वास्तव में घंटों से इसे न करने के बारे में चिंतित हैं तो आप उस क्षेत्र में बाधा डाल सकते हैं जो यह सुनिश्चित करने के लिए जांच करता है कि यह शून्य नहीं है। यह आपको बिना किसी चेक विकल्प के उपयोग करने की अनुमति देगा, और यह देखने के लिए कि क्या यह अपडेट हो रहा है, यह 4 मिलियन पंक्तियों में से प्रत्येक को चेक नहीं करता है।

  1. बाधा जो अपडेट होने से किसी भी नई पंक्तियाँ रोकने के लिए और मूल लोगों अनछुए छोड़ देंगे का उपयोग करें:

    CREATE TABLE Test 
    (
        T0 INT Not NULL, 
        T1 INT NUll 
    ) 
    
    INSERT INTO Test VALUES(1, NULL) -- Works! 
    
    ALTER TABLE Test 
        WITH NOCHECK 
         ADD CONSTRAINT N_null_test CHECK (T1 IS NOT NULL) 
    
        ALTER COLUMN T1 int NOT NULL 
    
    INSERT INTO Test VALUES(1, NULL) -- Doesn't work now! 
    

    सच आपके पास दो विकल्प (जोड़ा तीसरा संपादित देखें)।

  2. उन पंक्तियों को अपडेट करें जो किसी और चीज़ के लिए शून्य हैं और फिर नल ऑल्टर विकल्प लागू करें। यह वास्तव में ऑफ घंटों में चलाया जाना चाहिए, जब तक कि आप टेबल से लॉक होने वाली प्रक्रियाओं को ध्यान में रखते हैं।

आपके विशिष्ट परिदृश्य के आधार पर, विकल्प आपके लिए बेहतर हो सकता है। मैं विकल्प नहीं चुनूंगा क्योंकि आपको इसे बंद घंटे में चलाने की ज़रूरत है। लंबे समय तक, रात के मध्य में अपडेट करने का समय आपके सिरदर्द की तुलना में काफी हद तक खर्च किया जाएगा, जिससे आप कुछ घंटों को बचाने के लिए एक छोटा सा कटौती करके सामना करेंगे।

यह सब कहा जा रहा है, यदि आप विकल्प दो के साथ जाने जा रहे हैं तो आप ऑफ घंटे में किए गए काम की मात्रा को कम कर सकते हैं। क्या आप स्तंभ में फेरबदल से पहले पंक्तियों को रिक्त नहीं अद्यतन सुनिश्चित करने के लिए है के बाद से, आप के लिए धीरे-धीरे (एक ही बार में यह सब कर के सापेक्ष)

  1. देखने के लिए प्रत्येक पंक्ति
  2. चेक के माध्यम से जाओ एक कर्सर लिख सकते हैं यदि यह शून्य है
  3. इसे उचित रूप से अपडेट करें। इसमें कुछ समय लगेगा, लेकिन यह पूरे टेबल को अन्य प्रोग्राम्स को एक्सेस करने से रोक नहीं देगा। (with(rowlock) तालिका संकेत मत भूलना!)

संपादित: आप उचित कॉलम के साथ एक नया टेबल बना सकते हैं, और फिर मूल तालिका से डेटा निर्यात: मैं बस एक तीसरा विकल्प के बारे में सोचा नए के लिए। जब यह किया जाता है, तो आप मूल तालिका को छोड़ सकते हैं और नए के नाम को पुराने होने के लिए बदल सकते हैं। ऐसा करने के लिए आपको मूल पर निर्भरताओं को अक्षम करना होगा और जब आप पूरा कर लेंगे तो उन्हें नए पर बैक अप लेंगे, लेकिन यह प्रक्रिया आपके द्वारा ऑफ़लाइन घंटों में किए जाने वाले काम की मात्रा को बहुत कम कर देगी। यह वही दृष्टिकोण है जो एसक्यूएल सर्वर का उपयोग करता है जब आप प्रबंधन स्टूडियो के माध्यम से टेबल में कॉलम ऑर्डरिंग परिवर्तन करते हैं। इस दृष्टिकोण के लिए, मैं यह सुनिश्चित करने के लिए भाग में सम्मिलित करता हूं कि आप सिस्टम पर पूर्ववत तनाव नहीं डालते हैं और दूसरों को इसे एक्सेस करने से रोकते हैं। फिर ऑफ घंटों पर, आप मूल को छोड़ सकते हैं, दूसरे का नाम बदल सकते हैं, और निर्भरता आदि लागू कर सकते हैं। आपके पास अभी भी कुछ घंटे का काम होगा, लेकिन यह अन्य दृष्टिकोण की तुलना में कम होगा।

sp_rename का उपयोग करने के लिए लिंक।

+4

यदि आप कोई चेक नहीं करते हैं, तो बाधा विश्वसनीय नहीं होगी और क्वेरी ऑप्टिमाइज़र द्वारा इसका उपयोग नहीं किया जा सकता है। Http://sqlblog.com/blogs/tibor_karaszi/archive/2008/01/12/non-trusted-constraints-and-performance.aspx –

+3

इसके अलावा, NOCHECK कीवर्ड न्यूल/नॉट न्यूल पर लागू नहीं होता है। यह केवल उन बाधाओं पर लागू होता है जो कन्स्ट्रेंट खंड का हिस्सा हैं। –

+0

प्रश्न से ओपी पहले से ही सुनिश्चित कर चुका है कि उनके कॉलम में कोई 'शून्य' मान नहीं है, इसलिए आपके उत्तर के दूसरे भाग की प्रासंगिकता सुनिश्चित नहीं है? –

2

निराशा के लिए क्षमा करें, लेकिन:

  • यह गति पकड़ किसी भी तरीके: नहीं, नहीं करता है, तो आप तालिका संरचना में कोई
  • बदलना चाहते हैं या कर रहा हूँ मैं बस छूट के दौरान रात भर यह कर अटक घंटे? हां, और शायद यह सबसे अच्छा है, क्योंकि @HLGEM ने
  • को इंगित किया है, यह भी एक टेबल लॉक का कारण बन सकता है? हाँ

नहीं सीधे इस विषय पर आप के लिए प्रासंगिक (क्योंकि इसके बारे में शून्य करने के लिए शून्य नहीं से हो रहा है), लेकिन दिलचस्प पढ़ने: http://beyondrelational.com/blogs/sankarreddy/archive/2011/04/05/is-alter-table-alter-column-not-null-to-null-always-expensive.aspx

और अंत में कुछ प्राचीन इतिहास - एक बराबर प्रश्न पर एक मंच में में 2005, एक ही सुझाव के रूप में @Kevin ऊपर की पेशकश की बनाया गया था - बनाने insteadof की कोई समस्या का उपयोग कर स्तंभ में ही गैर-व्यर्थ: http://www.sqlteam.com/Forums/topic.asp?TOPIC_ID=50671

4

एक ही रास्ता करने के लिए इस "जल्दी" (*) कि मैं जानता हूँ कि की

कर रहा है
  • एक 'छाया' तालिका बनाना जिसमें आवश्यक लेआउट
  • स्रोत-तालिका में ट्रिगर जोड़ रहा है, इसलिए कोई भी सम्मिलित/अद्यतन/हटाएं ऑपरेशन छाया-तालिका में कॉपी किए गए हैं (किसी भी न्यूल को पकड़ने के लिए दिमाग जो पॉपअप हो सकता है!)
  • स्रोत से सभी डेटा को छाया-तालिका में कॉपी करें, संभावित रूप से छोटे टुकड़ों में (सुनिश्चित करें कि आप ट्रिगर द्वारा पहले से कॉपी किए गए डेटा को संभाल सकते हैं, सुनिश्चित करें कि डेटा नई संरचना में फिट होगा (ISNULL (?)) से/अन्य तालिकाओं
  • जब सब किया जाता है, एक स्पष्ट लेन-देन के अंदर निम्न करने के लिए सभी निर्भरता
  • स्क्रिप्ट बाहर:
    • स्रोत-टेबल
    • के लिए उनकी निर्भरता छोड़ने के लिए कुछ और करने के लिए स्रोत तालिका का नाम बदलने स्क्रिप्ट चलाने shadowtable
    • पर स्रोत-मेज पर एक विशेष तालिका ताला और एक मिल (जैसे प्रत्यय _old)
    • स्रोत तालिका के मूल नाम छाया तालिका का नाम बदलने
    • सभी निर्भरता फिर

आप लेन-देन एक के बाहर अंतिम चरण करना चाह सकते हैं बनाने के लिए स्क्रिप्ट को चलाने इस तालिका को संदर्भित करने वाली तालिकाओं की मात्रा और आकार के आधार पर इसमें काफी समय लग सकता है, पहले चरण में

पर अधिक समय नहीं लगेगा, हमेशा के रूप में, परीक्षण पर परीक्षण चलाने के लिए शायद सबसे अच्छा है - सर्वर पहले =)

पीएस: कृपया एफके के नोचैक के साथ पुन: प्रयास करने के लिए प्रलोभन न करें, यह उन्हें व्यर्थ प्रदान करता है क्योंकि अनुकूलक उन पर भरोसा नहीं करेगा और न ही उन्हें एक प्रश्न योजना बनाते समय विचार करेगा।

(*: जहां जल्दी करने के लिए नीचे आता है: कम से कम संभव डाउनटाइम के साथ)

+0

मैं पिछले सप्ताह के लिए इस विचार से टकरा रहा था, लेकिन हमारी विशिष्ट स्थिति में हमने समस्याओं को देखा क्योंकि कई स्तंभ परिवर्तन हो सकते हैं जो एक-दूसरे के बारे में नहीं जानते हैं, इसलिए गतिशील रूप से "इसके बजाय" ट्रिगर्स बनाना असंभव होगा (यह सब स्वचालित होना है)। आज सुबह यह हुआ कि यह टेबल संचालित हो सकता है और मैं यहां जवाब पोस्ट करने जा रहा था यह जानने के लिए कि आपने मुझे इसे हराया :) –

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