Database
 sql >> डेटाबेस >  >> RDS >> Database

हैलोवीन समस्या - भाग 2

[ भाग 1 | भाग 2 | भाग 3 | भाग 4 ]

इस श्रृंखला के पहले भाग में, हमने देखा कि कैसे हैलोवीन समस्या UPDATE पर लागू होती है प्रश्न। संक्षेप में संक्षेप में, समस्या यह थी कि अद्यतन करने के लिए अभिलेखों का पता लगाने के लिए उपयोग की जाने वाली एक अनुक्रमणिका में इसकी कुंजियों को अद्यतन संचालन द्वारा संशोधित किया गया था (कुंजी को विस्तारित करने के बजाय अनुक्रमणिका में शामिल स्तंभों का उपयोग करने का एक और अच्छा कारण)। क्वेरी ऑप्टिमाइज़र ने समस्या से बचने के लिए निष्पादन योजना के पढ़ने और लिखने के पक्षों को अलग करने के लिए एक ईगर टेबल स्पूल ऑपरेटर पेश किया। इस पोस्ट में, हम देखेंगे कि एक ही अंतर्निहित समस्या कैसे प्रभावित कर सकती है  INSERT और DELETE बयान।

विवरण सम्मिलित करें

अब हम उन शर्तों के बारे में कुछ जानते हैं जिनके लिए हैलोवीन सुरक्षा की आवश्यकता होती है, INSERT बनाना काफी आसान है। उदाहरण जिसमें एक ही इंडेक्स स्ट्रक्चर की चाबियों से पढ़ना और लिखना शामिल है। सबसे सरल उदाहरण तालिका में पंक्तियों का दोहराव है (जहां नई पंक्तियों को जोड़ना अनिवार्य रूप से संकुल सूचकांक की कुंजियों को संशोधित करता है):

CREATE TABLE dbo.Demo
(
    SomeKey integer NOT NULL,
 
    CONSTRAINT PK_Demo
        PRIMARY KEY (SomeKey)
);
 
INSERT dbo.Demo
SELECT SomeKey FROM dbo.Demo;

समस्या यह है कि निष्पादन योजना के पठन पक्ष द्वारा नई सम्मिलित पंक्तियों का सामना किया जा सकता है, जिसके परिणामस्वरूप संभावित रूप से एक लूप होता है जो पंक्तियों को हमेशा के लिए जोड़ता है (या कम से कम कुछ संसाधन सीमा तक पहुंचने तक)। क्वेरी अनुकूलक इस जोखिम को पहचानता है, और आवश्यक चरण पृथक्करण प्रदान करने के लिए एक उत्सुक तालिका स्पूल जोड़ता है :

एक और यथार्थवादी उदाहरण

आप शायद तालिका में प्रत्येक पंक्ति को डुप्लिकेट करने के लिए अक्सर प्रश्न नहीं लिखते हैं, लेकिन आप संभवतः ऐसे प्रश्न लिखते हैं जहां INSERT के लिए लक्ष्य तालिका होती है। SELECT . में भी कहीं दिखाई देता है खंड। एक उदाहरण स्टेजिंग टेबल से पंक्तियों को जोड़ना है जो पहले से ही गंतव्य में मौजूद नहीं है:

CREATE TABLE dbo.Staging
(
    SomeKey integer NOT NULL
);
 
-- Sample data
INSERT dbo.Staging
    (SomeKey)
VALUES
    (1234),
    (1234);
 
-- Test query
INSERT dbo.Demo
SELECT s.SomeKey
FROM dbo.Staging AS s
WHERE NOT EXISTS
(
    SELECT 1
    FROM dbo.Demo AS d
    WHERE d.SomeKey = s.SomeKey
);

निष्पादन योजना है:

इस मामले में समस्या सूक्ष्म रूप से भिन्न है, हालांकि अभी भी उसी मूल मुद्दे का एक उदाहरण है। लक्ष्य डेमो तालिका में कोई मान '1234' नहीं है, लेकिन स्टेजिंग तालिका में ऐसी दो प्रविष्टियाँ हैं। चरण पृथक्करण के बिना, सामने आया पहला '1234' मान सफलतापूर्वक डाला जाएगा, लेकिन दूसरी जांच में पता चलेगा कि '1234' मान अब मौजूद है और इसे फिर से सम्मिलित करने का प्रयास नहीं करेगा। संपूर्ण रूप से कथन सफलतापूर्वक पूरा होगा।

यह इस विशेष मामले में एक वांछनीय परिणाम उत्पन्न कर सकता है (और यहां तक ​​​​कि सहज रूप से सही भी लग सकता है) लेकिन यह एक सही कार्यान्वयन नहीं है। SQL मानक के लिए आवश्यक है कि डेटा संशोधन क्वेरी को इस तरह निष्पादित किया जाए जैसे कि पढ़ने, लिखने और जाँचने के तीन चरण पूरी तरह से अलग-अलग होते हैं (भाग एक देखें)।

एकल ऑपरेशन के रूप में सम्मिलित करने के लिए सभी पंक्तियों की खोज करते हुए, हमें स्टेजिंग तालिका से दोनों '1234' पंक्तियों का चयन करना चाहिए, क्योंकि यह मान अभी तक लक्ष्य में मौजूद नहीं है। इसलिए निष्पादन योजना को दोनों को सम्मिलित करने का प्रयास करना चाहिए स्टेजिंग टेबल से '1234' पंक्तियां, जिसके परिणामस्वरूप प्राथमिक कुंजी का उल्लंघन हुआ:

संदेश 2627, स्तर 14, राज्य 1, पंक्ति 1
प्राथमिक कुंजी बाधा 'पीके_डेमो' का उल्लंघन।
ऑब्जेक्ट 'dbo.Demo' में डुप्लिकेट कुंजी सम्मिलित नहीं कर सकता।
डुप्लिकेट कुंजी मान है ( 1234).
विवरण समाप्त कर दिया गया है।

टेबल स्पूल द्वारा प्रदान किया गया चरण पृथक्करण यह सुनिश्चित करता है कि लक्ष्य तालिका में कोई भी परिवर्तन किए जाने से पहले अस्तित्व के लिए सभी जांच पूरी हो जाएं। यदि आप उपरोक्त नमूना डेटा के साथ SQL सर्वर में क्वेरी चलाते हैं, तो आपको (सही) त्रुटि संदेश प्राप्त होगा।

INSERT कथनों के लिए हैलोवीन सुरक्षा आवश्यक है जहां लक्ष्य तालिका को SELECT खंड में भी संदर्भित किया जाता है।

विवरण हटाएं

हम उम्मीद कर सकते हैं कि हैलोवीन समस्या DELETE . पर लागू न हो कथन, क्योंकि यदि हम एक पंक्ति को कई बार हटाने का प्रयास करते हैं तो यह वास्तव में मायने नहीं रखता है। हम अपने स्टेजिंग टेबल उदाहरण को निकालने . के लिए संशोधित कर सकते हैं डेमो टेबल से पंक्तियाँ जो स्टेजिंग में मौजूद नहीं हैं:

TRUNCATE TABLE dbo.Demo;
TRUNCATE TABLE dbo.Staging;
 
INSERT dbo.Demo (SomeKey) VALUES (1234);
 
DELETE dbo.Demo
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM dbo.Staging AS s 
    WHERE s.SomeKey = dbo.Demo.SomeKey
);

यह परीक्षण हमारे अंतर्ज्ञान को मान्य करता है क्योंकि निष्पादन योजना में कोई टेबल स्पूल नहीं है:

इस प्रकार का DELETE चरण पृथक्करण की आवश्यकता नहीं है क्योंकि प्रत्येक पंक्ति में एक विशिष्ट पहचानकर्ता होता है (एक RID यदि तालिका एक ढेर है, क्लस्टर इंडेक्स कुंजी और संभवतः अन्यथा एक अद्वितीय)। यह अद्वितीय पंक्ति लोकेटर एक स्थिर कुंजी है - ऐसा कोई तंत्र नहीं है जिसके द्वारा इस योजना के क्रियान्वयन के दौरान यह बदल सकता है, इसलिए हैलोवीन समस्या उत्पन्न नहीं होती है।

हैलोवीन सुरक्षा हटाएं

फिर भी, कम से कम एक ऐसा मामला है जहां DELETE हैलोवीन सुरक्षा की आवश्यकता है:जब योजना हटाई जा रही तालिका के अलावा तालिका में एक पंक्ति का संदर्भ देती है। इसके लिए स्व-जुड़ने की आवश्यकता होती है, जो आमतौर पर तब पाया जाता है जब पदानुक्रमित संबंधों को मॉडल किया जाता है। एक सरलीकृत उदाहरण नीचे दिखाया गया है:

CREATE TABLE dbo.Test
(
    pk char(1) NOT NULL,
    ref char(1) NULL,
 
    CONSTRAINT PK_Test
        PRIMARY KEY (pk)
);
 
INSERT dbo.Test
    (pk, ref)
VALUES
    ('B', 'A'),
    ('C', 'B'),
    ('D', 'C');

यहां वास्तव में एक समान-तालिका विदेशी कुंजी संदर्भ होना चाहिए, लेकिन आइए उस डिज़ाइन को एक पल के लिए विफल होने पर ध्यान न दें - संरचना और डेटा फिर भी मान्य हैं (और यह वास्तविक दुनिया में छोड़ी गई विदेशी कुंजियों को खोजने के लिए दुख की बात है)। वैसे भी, हाथ में किसी भी पंक्ति को हटाना है जहां रेफरी स्तंभ एक गैर-मौजूद pk की ओर इशारा करता है मूल्य। प्राकृतिक DELETE इस आवश्यकता से मेल खाने वाली क्वेरी है:

DELETE dbo.Test
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM dbo.Test AS t2 
    WHERE t2.pk = dbo.Test.ref
);

क्वेरी योजना है:

ध्यान दें कि इस योजना में अब एक महंगा ईगर टेबल स्पूल है। यहां चरण पृथक्करण की आवश्यकता है क्योंकि अन्यथा परिणाम उस क्रम पर निर्भर हो सकते हैं जिसमें पंक्तियों को संसाधित किया जाता है:

यदि निष्पादन इंजन उस पंक्ति से शुरू होता है जहां pk =बी, इसे कोई मेल खाने वाली पंक्ति नहीं मिलेगी (संदर्भ =ए और ऐसी कोई पंक्ति नहीं है जहां pk =ए)। यदि निष्पादन तब उस पंक्ति पर जाता है जहां pk =C, इसे भी हटा दिया जाएगा क्योंकि हमने इसके ref . द्वारा इंगित पंक्ति B को अभी-अभी हटा दिया है कॉलम। अंतिम परिणाम यह होगा कि इस क्रम में पुनरावृत्त प्रसंस्करण तालिका से सभी पंक्तियों को हटा देगा, जो स्पष्ट रूप से गलत है।

दूसरी ओर, यदि निष्पादन इंजन pk . के साथ पंक्ति को संसाधित करता है =D पहले, यह एक मेल खाने वाली पंक्ति ढूंढेगा (ref =सी)। यह मानते हुए कि निष्पादन उल्टा जारी रहा pk आदेश, तालिका से हटाई गई एकमात्र पंक्ति वही होगी जहां pk =बी। यह सही परिणाम है (याद रखें कि क्वेरी को निष्पादित किया जाना चाहिए जैसे कि पढ़ना, लिखना और सत्यापन चरण क्रमिक रूप से और बिना ओवरलैप के हुए थे)।

बाधा सत्यापन के लिए चरण पृथक्करण

एक तरफ, हम चरण पृथक्करण का एक और उदाहरण देख सकते हैं यदि हम पिछले उदाहरण में समान-तालिका विदेशी कुंजी बाधा जोड़ते हैं:

DROP TABLE dbo.Test;
 
CREATE TABLE dbo.Test
(
    pk char(1) NOT NULL,
    ref char(1) NULL,
 
    CONSTRAINT PK_Test
        PRIMARY KEY (pk),
 
    CONSTRAINT FK_ref_pk
        FOREIGN KEY (ref)
        REFERENCES dbo.Test (pk)
);
 
INSERT dbo.Test
    (pk, ref)
VALUES
    ('B', NULL),
    ('C', 'B'),
    ('D', 'C');

INSERT के लिए निष्पादन योजना है:

इंसर्ट को हैलोवीन सुरक्षा की आवश्यकता नहीं है क्योंकि योजना एक ही तालिका से नहीं पढ़ती है (डेटा स्रोत एक इन-मेमोरी वर्चुअल टेबल है जिसे कॉन्स्टेंट स्कैन ऑपरेटर द्वारा दर्शाया गया है)। हालाँकि SQL मानक के लिए आवश्यक है कि चरण 3 (बाधा जाँच) लेखन चरण पूरा होने के बाद हो। इस कारण से, एक चरण पृथक्करण ईगर टेबल स्पूल को योजना में जोड़ा जाता है बाद क्लस्टर्ड इंडेक्स इंडेक्स, और प्रत्येक पंक्ति की जाँच से ठीक पहले यह सुनिश्चित करने के लिए कि विदेशी कुंजी बाधा वैध बनी हुई है।

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

DELETE कथनों के लिए हैलोवीन सुरक्षा की आवश्यकता होती है, जहां लक्ष्य तालिका का स्वयं-जुड़ना मौजूद होता है।

सारांश

हैलोवीन प्रोटेक्शन निष्पादन योजनाओं में एक महंगी (लेकिन आवश्यक) विशेषता हो सकती है जो डेटा को बदल देती है (जहां 'परिवर्तन' में सभी SQL सिंटैक्स शामिल होते हैं जो पंक्तियों को जोड़ते, बदलते या हटाते हैं)। UPDATE . के लिए हैलोवीन सुरक्षा आवश्यक है योजनाएं जहां एक सामान्य अनुक्रमणिका संरचना की कुंजियों को पढ़ा और संशोधित किया जाता है, INSERT . के लिए योजनाएँ जहाँ लक्ष्य तालिका को योजना के पठन पक्ष पर संदर्भित किया जाता है, और DELETE . के लिए योजनाएँ जहाँ लक्ष्य तालिका पर स्वयं-जुड़ने का प्रदर्शन किया जाता है।

इस श्रृंखला के अगले भाग में कुछ विशेष हेलोवीन समस्या अनुकूलन शामिल होंगे जो केवल MERGE . पर लागू होते हैं बयान।

[ भाग 1 | भाग 2 | भाग 3 | भाग 4 ]


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Django की नई पोस्टग्रेज़ सुविधाओं के साथ मज़ा

  2. डाटाबेस सबसेटिंग - आईआरआई वोरसिटी में कैसे करें

  3. एक किराना वितरण डेटा मॉडल

  4. SQL में बाधा की जाँच करें

  5. वर्किंग फोल्डर सोर्स कंट्रोल का उपयोग करके डेटाबेस परिवर्तन को ट्रैक करना