जल्दी से NULL कॉलम को NULL में न बदलें


11

मेरे पास लाखों पंक्तियों वाली एक तालिका है और एक स्तंभ है जो NULL मानों की अनुमति देता है। हालाँकि किसी भी पंक्ति में वर्तमान में उस कॉलम के लिए NULL मान नहीं है (मैं इसे क्वेरी के साथ काफी जल्दी सत्यापित कर सकता हूं)। हालांकि जब मैं कमांड निष्पादित करता हूं

ALTER TABLE MyTable ALTER COLUMN MyColumn BIGINT NOT NULL;

क्वेरी हमेशा के लिए अपेक्षाकृत बोल लेती है । यह वास्तव में 10 और 20 मिनट के बीच लेता है, एक चेक बाधा को जोड़ने के रूप में दो बार से अधिक। क्या उस स्तंभ के लिए तालिका के मेटाडेटा को तुरंत अपडेट करने का एक तरीका है, खासकर जब से मुझे पता है कि उस स्तंभ के लिए किसी पंक्ति का कोई पूर्ण मान नहीं है?


2
नहीं (या कम से कम प्रलेखित / समर्थित विधियों का उपयोग नहीं)। यह देखें कि ALTER COLUMN बड़े पैमाने पर लॉग फ़ाइल वृद्धि का कारण नहीं बनता है?
मार्टिन स्मिथ

2
यह संभवतः Sch-M"हमेशा के लिए" लगने पर लॉक का इंतजार कर सकता है । आपने यह देखने के लिए इंतजार किया कि क्या वह इंतजार कर रहा था या व्यस्त था?
मार्टिन स्मिथ

@MartinSmith मैं स्पष्ट किया है कि मैं क्या मतलब हमेशा के लिए । मैं डेटाबेस के टकराने के बिना किसी अन्य सत्र के साथ एक समर्पित वातावरण में यह परीक्षण कर रहा हूं। यह आखिरकार पूरा करता है। लेकिन आपने जो उत्तर दिया वह बताता है कि इसमें इतना समय क्यों लगता है। यदि आप अपनी टिप्पणी को एक उत्तर के रूप में पुनः लिख सकते हैं, तो मैं इसे स्वीकार करूंगा।
जोसेफ Daigle

जवाबों:


12

@ ypercube का उत्तर आंशिक रूप से केवल मेटाडेटा के रूप में इस परिवर्तन को प्रबंधित करता है।

इस बाधा के साथ जोड़ने का NOCHECKमतलब है कि इसे सत्यापित करने के लिए किसी पंक्तियों को पढ़ने की आवश्यकता नहीं होगी, और यदि आप उस स्थिति से शुरू कर रहे हैं, जिसमें स्तंभ में NULLमान नहीं हैं (और यदि आपको पता है कि जाँच और बाधा जोड़ने के बीच कोई भी जोड़ा नहीं जाएगा), क्योंकि बाधा NULLभविष्य INSERTया UPDATEसंचालन से पैदा होने वाले मूल्यों को रोकती है , यह काम करेगा।

बाधा को जोड़ने पर अभी भी समवर्ती लेनदेन पर प्रभाव पड़ सकता है। ALTER TABLEएक प्राप्त करने की आवश्यकता होगी Sch-Mपहली ताला। जब तक यह प्रतीक्षा कर रहा है तब तक तालिका के अन्य सभी उपयोग यहां बताए गए अनुसार अवरुद्ध हो जाएंगे ।

एक बार Sch-Mताला अधिग्रहित हो जाने के बाद भी ऑपरेशन बहुत जल्दी होना चाहिए।

इसके साथ एक समस्या यह है कि भले ही आपको पता हो कि वास्तव में कॉलम में कोई NULLभी बाधा नहीं है, लेकिन क्वेरी ऑप्टिमाइज़र द्वारा भरोसा नहीं किया जाता है, जिसका अर्थ है कि योजनाएँ उप इष्टतम हो सकती हैं।

CREATE TABLE T (X INT NULL)

INSERT INTO T 
SELECT ROW_NUMBER() OVER (ORDER BY @@SPID)
FROM master..spt_values

ALTER TABLE T WITH NOCHECK
  ADD  CONSTRAINT X_NOT_NULL 
    CHECK (X IS NOT NULL) ; 

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

योजना

इसकी तुलना सरल से करें

ALTER TABLE T ALTER COLUMN X INT NOT NULL

SELECT *
FROM T 
WHERE X NOT IN (SELECT X FROM T)

योजना

इस तरह से कॉलम की परिभाषा को बदलने के साथ एक संभावित समस्या यह हो सकती है कि यह न केवल यह सत्यापित करने के लिए सभी पंक्तियों को पढ़ने की जरूरत है कि वे शर्त को पूरा करते हैं, बल्कि पंक्तियों में वास्तव में लॉग किए गए अपडेट को समाप्त कर सकते हैं

एक आधा रास्ता घर चेक बाधा को जोड़ने के लिए हो सकता है WITH CHECK। यह WITH NOCHECKसभी पंक्तियों को पढ़ने की आवश्यकता की तुलना में धीमा होगा, लेकिन यह क्वेरी ऑप्टिमाइज़र को ऊपर की क्वेरी में सरल योजना देने की अनुमति देता है और इसे संभव लॉग इन अद्यतन समस्या से बचना चाहिए।


7

आप कॉलम को बदलने के बजाय, विकल्प के CHECKसाथ एक तालिका बाधा जोड़ सकते हैं NOCHECK:

ALTER TABLE MyTable WITH NOCHECK
  ADD  CONSTRAINT MyColumn_NOT_NULL 
    CHECK (MyColumn IS NOT NULL) ;

1
यह भविष्य के अद्यतन या आवेषण को रोकता है जो स्तंभ बनाते हैं NULLलेकिन क्वेरी ऑप्टिमाइज़र द्वारा उपयोग नहीं किया जा सकेगा।
मार्टिन स्मिथ

@MartinSmith ओह हाँ, मैं बस इसी तरह के सवाल का जवाब और टिप्पणियाँ पढ़ता हूं: आप SQL सर्वर में बड़ी तालिका में एक नॉट कॉलम को कैसे जोड़ते हैं? कृपया, समस्याओं या बेहतर समाधान के साथ एक उत्तर जोड़ें और मैं अपना निकाल दूंगा।
ypercube y

2
मेरे पास बेहतर समाधान नहीं है। मैंने इसे अपग्रेड किया क्योंकि यह एक आंशिक समाधान प्रदान करता है। यदि सभी ओपी करना चाहते हैं तो अवैध डेटा को रोकने के लिए यह काम करेगा (और ALTER COLUMNएक बार Sch-Mलॉक हासिल करने की तुलना में तेज होना चाहिए क्योंकि इससे पंक्तियों को स्कैन करने की आवश्यकता नहीं है)। केवल यह बताते हुए कि यह काफी समान नहीं है (उदाहरण के लिए यदि NOT INयोजना में उपयोग की जाने वाली योजना अधिक जटिल होगी)
मार्टिन स्मिथ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.