प्राथमिक कुंजी पर स्व-जुड़ें


9

इस प्रश्न पर विचार करें जिसमें Nआत्म-जुड़ाव शामिल हैं:

select
    t1.*
from [Table] as t1
join [Table] as t2 on
    t1.Id = t2.Id
-- ...
join [Table] as tN on
    t1.Id = tN.Id

यह एन क्लस्टर इंडेक्स स्कैन और एन -1 मर्ज जॉइन के साथ एक निष्पादन योजना तैयार करता है।

ईमानदारी से, मुझे कोई कारण नहीं दिखता है कि सभी जॉइन को ऑप्टिमाइज़ न करें और केवल एक क्लस्टर इंडेक्स स्कैन करें, यानी मूल क्वेरी को ऑप्टिमाइज़ करें:

select
    t1.*
from [Table] as t1

प्रशन

  • क्यों नहीं जोड़ रहे हैं दूर अनुकूलित?
  • क्या यह कहना गणितीय रूप से गलत है कि हर जॉइन में परिणाम सेट नहीं बदलता है?

पर परीक्षण किया गया:

  • स्रोत सर्वर संस्करण: SQL सर्वर 2014 (12.0.4213)
  • स्रोत डेटाबेस इंजन संस्करण: Microsoft SQL सर्वर मानक संस्करण
  • स्रोत डेटाबेस इंजन प्रकार: स्टैंडअलोन SQL सर्वर
  • संगतता स्तर: SQL सर्वर 2008 (100)

प्रश्न सार्थक नहीं है; यह सिर्फ मेरे दिमाग में आया और मैं इसके बारे में उत्सुक हूं।

यहां बताया गया है बेला के साथ: तालिका बनाने और 3 प्रश्नों के साथ inner join'के साथ है, left joinऔर मिश्रित'। आप वहां निष्पादन योजना को भी देख सकते हैं।

ऐसा लगता है कि left joins परिणाम निष्पादन योजना में समाप्त हो गए inner joinहैं जबकि s नहीं हैं। अभी भी नहीं मिलता है , यद्यपि।

जवाबों:


18

सबसे पहले, मान लेते हैं कि (id)तालिका की प्राथमिक कुंजी है। इस मामले में, हाँ, जोड़ (साबित किए जा सकते हैं) निरर्थक हैं और उन्हें समाप्त किया जा सकता है।

अब यह सिर्फ सिद्धांत है - या गणित। ऑप्टिमाइज़र के लिए एक वास्तविक उन्मूलन करने के लिए, सिद्धांत को कोड में परिवर्तित किया गया है और ऑप्टिमाइज़र के ऑप्टिमाइज़ेशन ऑफ़ ऑप्टिमाइज़ेशन / रीराइटिंग / एलिमिनेशन में जोड़ा गया है। ऐसा होने के लिए, (DBMS) डेवलपर्स को यह सोचना चाहिए कि इससे दक्षता में अच्छे लाभ होंगे और यह एक सामान्य पर्याप्त मामला है।

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

उस ने कहा, ऐसे ही सवाल हैं जहां उन्मूलन होता है। रोब फ़ार्ले द्वारा एक बहुत अच्छी संबंधित ब्लॉग पोस्ट है: SQL सर्वर में शामिल करें

हमारे मामले में, हम सभी को जोड़ों में बदलाव करने के लिए करना होगा LEFTDbfiddle.uk देखें । इस मामले में आशावादी जानता है कि संभवतः परिणामों को बदलने के बिना सम्मिलित रूप से सुरक्षित रूप से हटाया जा सकता है। (सरलीकरण तर्क काफी सामान्य है और स्व-जोड़ों के लिए विशेष-आवरण नहीं है।)

पाठ्यक्रम की मूल क्वेरी में, जॉइन को हटाने INNERसे परिणाम या तो बदल नहीं सकते हैं। लेकिन यह प्राथमिक कुंजी पर स्वयं से जुड़ने के लिए बिल्कुल भी सामान्य नहीं है, इसलिए ऑप्टिमाइज़र के पास यह मामला लागू नहीं होता है। हालांकि इसमें शामिल होना आम है (या ज्वाइन लेफ्ट) जहां ज्वाइन किया गया कॉलम टेबल में से एक की प्राथमिक कुंजी है (और अक्सर एक विदेशी कुंजी बाधा होती है)। जो जुओं को खत्म करने के लिए एक दूसरा विकल्प देता है: एक जोड़ें (स्वयं संदर्भित) विदेशी कुंजी बाधा:

ALTER TABLE "Table"
    ADD FOREIGN KEY (id) REFERENCES "Table" (id) ;

और वोइला, जोड़ ख़त्म हो जाते हैं! (एक ही बेला में परीक्षण): यहाँ

create table docs
(id int identity primary key,
 doc varchar(64)
) ;
GO
insert
into docs (doc)
values ('Enter one batch per field, don''t use ''GO''')
     , ('Fields grow as you type')
     , ('Use the [+] buttons to add more')
     , ('See examples below for advanced usage')
  ;
GO
4 पंक्तियां प्रभावित
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1 
    join docs d2 on d2.id=d1.id
    join docs d3 on d3.id=d1.id
    join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
आईडी | दस्तावेज़                                      
-: | : ----------------------------------------
 1 | प्रति फ़ील्ड एक बैच दर्ज करें, 'GO' का उपयोग न करें
 2 | जैसे ही आप टाइप करते हैं फील्ड्स बढ़ने लगते हैं                  
 3 | अधिक जोड़ने के लिए [+] बटन का उपयोग करें          
 4 | उन्नत उपयोग के लिए नीचे दिए गए उदाहरण देखें    

यहां छवि विवरण दर्ज करें

--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1 
    left join docs d2 on d2.id=d1.id
    left join docs d3 on d3.id=d1.id
    left join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
आईडी | दस्तावेज़                                      
-: | : ----------------------------------------
 1 | प्रति फ़ील्ड एक बैच दर्ज करें, 'GO' का उपयोग न करें
 2 | जैसे ही आप टाइप करते हैं फील्ड्स बढ़ने लगते हैं                  
 3 | अधिक जोड़ने के लिए [+] बटन का उपयोग करें          
 4 | उन्नत उपयोग के लिए नीचे दिए गए उदाहरण देखें    

यहां छवि विवरण दर्ज करें

alter table docs
  add foreign key (id) references docs (id) ;
GO
--------------------------------------------------------------------------------
-- Or use XML to see the visual representation, thanks to Justin Pealing and
-- his library: https://github.com/JustinPealing/html-query-plan
--------------------------------------------------------------------------------
set statistics xml on;
select d1.* from docs d1 
    join docs d2 on d2.id=d1.id
    join docs d3 on d3.id=d1.id
    join docs d4 on d4.id=d1.id;
set statistics xml off;
GO
आईडी | दस्तावेज़                                      
-: | : ----------------------------------------
 1 | प्रति फ़ील्ड एक बैच दर्ज करें, 'GO' का उपयोग न करें
 2 | जैसे ही आप टाइप करते हैं फील्ड्स बढ़ने लगते हैं                  
 3 | अधिक जोड़ने के लिए [+] बटन का उपयोग करें          
 4 | उन्नत उपयोग के लिए नीचे दिए गए उदाहरण देखें    

यहां छवि विवरण दर्ज करें


2

संबंधपरक शब्दों में, कोई भी नाम बिना विशेषता के नामकरण के बिना एक सेशन है और इसे निष्पादन योजनाओं से सुरक्षित रूप से समाप्त किया जा सकता है। दुर्भाग्य से एसक्यूएल संबंधपरक नहीं है और वह स्थिति जहां स्वप्रेरक को ऑप्टिमाइज़र द्वारा समाप्त किया जा सकता है, बहुत कम संख्या में किनारे के मामलों तक सीमित है।

एसक्यूएल का सिलेक्ट सिंटैक्स प्रोजेक्शन पर तार्किक पूर्वता में शामिल हो जाता है। कॉलम नामों और डुप्लिकेट कॉलम नामों और अन-नेम कॉलम के लिए एसक्यूएल के स्कोपिंग नियमों की अनुमति है, रिलेशनल बीजगणित के अनुकूलन की तुलना में एसक्यूएल क्वेरी अनुकूलन को काफी कठिन बना देता है। SQL DBMS विक्रेताओं के पास सीमित संसाधन हैं और उन्हें किस प्रकार के अनुकूलन का समर्थन करना है, इसके बारे में चयनात्मक होना चाहिए।


1

प्राथमिक कुंजी हमेशा अद्वितीय होती है और शून्य मानों को अनुमति नहीं दी जाती है इसलिए प्राथमिक कुंजियों पर तालिका में शामिल होने के लिए (स्वयं संदर्भित द्वितीयक कुंजी के साथ नहीं और जहां कथन नहीं हैं) मूल तालिका के समान पंक्तियों का उत्पादन करेंगे।

जैसा कि वे इसे अनुकूलित नहीं करते हैं, मैं कहूंगा कि यह एक ऐसा किनारा मामला है जिसकी उन्होंने या तो योजना नहीं बनाई थी या लोगों ने ऐसा नहीं किया था। गारंटीकृत अद्वितीय प्राथमिक कुंजियों पर स्वयं एक तालिका में शामिल होने से कोई उद्देश्य पूरा नहीं होता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.