क्या मुझे SQL सर्वर में बाहरी जोड़ पर निर्भर रहना चाहिए?


9

मैंने इस पर मिश्रित जानकारी सुनी है और एक विहित या विशेषज्ञ की राय की उम्मीद कर रहा हूं।

यदि मेरे पास कई LEFT OUTER JOINएस हैं, तो प्रत्येक अंतिम पर निर्भर है, क्या उन्हें घोंसला बनाना बेहतर है?

एक काल्पनिक उदाहरण के लिए, JOINकरने के लिए MyParentपर निर्भर करता है JOINके लिए MyChild: http://sqlfiddle.com/#!3/31022/5

SELECT
    {columns}
FROM
    MyGrandChild AS gc
LEFT OUTER JOIN
    MyChild AS c
        ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN
    MyParent AS p
        ON p.[id] = c.[ParentId]

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

Http://sqlfiddle.com/#! -3/31022/7 की तुलना में

SELECT
    {columns}
FROM
    MyGrandChild AS gc
LEFT OUTER JOIN
    (
    MyChild AS c            
    LEFT OUTER JOIN
        MyParent AS p
            ON p.[id] = c.[ParentId]
    )
    ON c.[Id] = gc.[ParentId]

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

जैसा कि ऊपर दिखाया गया है ये SS2k8 में अलग-अलग क्वेरी प्लान बनाते हैं


मुझे नेस्टेड जॉइन का उपयोग करना पसंद है: michaeljswart.com/2012/09/when-i-use-nested-joins यह हालांकि स्टाइल की बात हो सकती है।
माइकल जे। स्वार्ट

अपने ब्लॉग पर ही निर्भर चर्चा करने के लिए प्रकट होता है @MichaelJSwart JOINएक हैINNER JOIN
मैथ्यू

1
आप "बेहतर" को कैसे परिभाषित करना चाहते हैं? व्यक्तिगत रूप से, मुझे पढ़ने में सबसे आसान लगता है - मेरा मन रिश्ते को उलटने की कोशिश करने के आसपास नहीं उछलता है। ON ... ONएक पंक्ति (कोष्ठक या नहीं) में दो बार होने से बहुत भ्रम होता है।
हारून बर्ट्रेंड

4
जब मुझे कुछ करने के दो तरीकों के बीच कोई प्रदर्शन अंतर नहीं मिलता है, तो अगला सवाल मैं खुद से पूछता हूं: अगर मैं आज रात किसी बस से टकरा गया या लॉटरी जीत गया, तो कौन सा संस्करण सबसे आसानी से समझ में आ जाएगा और जो कोई भी मेरे कोड को लेगा ?
हारून बर्ट्रेंड

1
use planसंकेत काम करता है जब लेकिन इसके विपरीत नहीं पहले से पीछे नहीं क्वेरी योजना रोपाई।
मार्टिन स्मिथ

जवाबों:


3

यह पूरी तरह से एक विहित जवाब नहीं है, लेकिन मैंने देखा है कि SQL फिडेल में दिखाए गए नेस्टेड लूप्स क्वेरी प्लान के लिए क्विंट 2 से क्वैरी 1 तक की योजना को USE PLANसंकेत के उपयोग के साथ लागू करना संभव था, लेकिन रिवर्स ऑपरेशन का प्रयास विफल रहा

क्वेरी प्रोसेसर क्वेरी योजना का उत्पादन नहीं कर सका क्योंकि USE PLAN संकेत में वह योजना होती है जिसे क्वेरी के लिए वैध होने के लिए सत्यापित नहीं किया जा सकता है। USE PLAN संकेत निकालें या प्रतिस्थापित करें। सफल योजना के सर्वोत्तम संभावना के लिए, सत्यापित करें कि USE PLAN संकेत में प्रदान की गई योजना एक ही क्वेरी के लिए SQL सर्वर द्वारा स्वचालित रूप से बनाई गई है।

ऑप्टिमाइज़र परिवर्तन नियम ReorderLOJN को अक्षम करने से पहले की सफल योजना संकेत को भी सफल होने से रोकता है।

अधिक मात्रा में डेटा के साथ प्रयोग करने से पता चलता है कि एसक्यूएल सर्वर निश्चित रूप (A LOJ B) LOJ Cसे A LOJ (B LOJ C)स्वाभाविक रूप से रूपांतरित करने में सक्षम है, लेकिन मुझे ऐसा कोई प्रमाण नहीं मिला कि रिवर्स सच है।

एक बहुत ही विवादित मामला जहां पहली क्वेरी दूसरी से बेहतर प्रदर्शन करती है

DROP TABLE  MyGrandChild , MyChild,  MyParent

CREATE TABLE MyParent
(Id int)

CREATE TABLE MyChild
(Id int PRIMARY KEY
,ParentId int,
Filler char(8000) NULL)

CREATE TABLE MyGrandChild
(Id int
,ParentId int)

INSERT INTO MyChild
                      (Id, ParentId)
SELECT TOP (100000) ROW_NUMBER() OVER (ORDER BY @@SPID),
                     ROW_NUMBER() OVER (ORDER BY @@SPID)    
FROM master..spt_values  v1, master..spt_values                  

INSERT INTO MyGrandChild
                      (Id, ParentId)
OUTPUT INSERTED.Id INTO MyParent
SELECT TOP (3000) Id, Id AS ParentId
FROM MyChild
ORDER BY Id

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

SELECT gc.Id       AS gcId,
       gc.ParentId AS gcpId,
       c.Id        AS cId,
       c.ParentId  AS cpId,
       p.Id        AS pId
FROM   MyGrandChild AS gc
       LEFT OUTER JOIN MyChild AS c
         ON c.[Id] = gc.[ParentId]
       LEFT OUTER JOIN MyParent AS p
         ON p.[Id] = c.[ParentId]

SELECT gc.Id       AS gcId,
       gc.ParentId AS gcpId,
       c.Id        AS cId,
       c.ParentId  AS cpId,
       p.Id        AS pId
FROM   MyGrandChild AS gc
       LEFT OUTER JOIN( MyChild AS c
                        LEFT OUTER JOIN MyParent AS p
                          ON p.[Id] = c.[ParentId])
         ON c.[Id] = gc.[ParentId] 

जो योजना देता है

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

मेरे लिए क्वेरी 1 में क्वेरी 2 के लिए 108 एमएस बनाम 1,163 एमएस का एक विस्तृत समय था।

प्रश्न 1

Table 'Worktable'. Scan count 0, logical reads 0 
Table 'MyChild'. Scan count 0, logical reads 9196
Table 'MyGrandChild'. Scan count 1, logical reads 7
Table 'MyParent'. Scan count 1, logical reads 5

प्रश्न २

Table 'MyParent'. Scan count 1, logical reads 15000
Table 'MyChild'. Scan count 0, logical reads 9000 
Table 'MyGrandChild'. Scan count 1, logical reads 7

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

यह अच्छी तरह से काउंटर उदाहरणों के साथ आने के लिए पूरी तरह से संभव हो सकता है जहां क्वेरी 2 बेहतर प्रदर्शन करती है। दोनों का प्रयास करें और निष्पादन योजनाओं को देखें।


-1

"Nested Join" नाम का कोई ऐसा JOIN टाइप नहीं है। यह लिखने की एक और भिन्नता है जोइन पठनीयता के उद्देश्य से हो सकती है। आप उन्हें केवल समझने के उद्देश्य के लिए एक "उप प्रश्न" के रूप में देख सकते हैं।

यदि आप कोड पठनीयता के बारे में अधिक चिंतित हैं तो मेरा लेना है, यह व्यक्ति की पसंद है कि वे किसके साथ मिलनसार हैं।

और यदि आप क्वेरी के प्रदर्शन से चिंतित हैं, और क्वेरी में "Force JOIN ORDER" संकेत का उपयोग नहीं किया जाता है, तो इससे कोई फर्क नहीं पड़ता कि क्या क्वेरी "Nested Join" या All "Outer Join" के साथ लिखी गई है। SQL सर्वर दो तालिकाओं और / या परिणाम में शामिल होने की लागत के आधार पर आदेश के साथ आता है। SQL सर्वर एक समय में डेटा के दो सेटों के बीच JOIN करता है।

वास्तव में, कल्पना करें कि यदि SQL सर्वर दूसरे भाग को करने के लिए "नेस्टेड जॉइन" करता है, तो "MyChild AS c LEFT OUTER JOIN MyParent AS p ON p। [id] = c। [ParentIdd" और उन तालिका में होता है। पंक्तियाँ है कि अगले बाएँ में छोड़ने के लिए जा रहे हैं। उस स्थिति में SQL सर्वर ने इन दोनों को OUTER JOIN करने और उस परिणाम को अगले JOIN पर भेजने में अनावश्यक संसाधन खर्च किए हैं।

आप यहां भी इसी तरह के सवाल पूछे और जवाब दे सकते हैं। 'नेस्टेड ज्वाइन' सिंटेक्स को समझना


1
फिर, वे FORCE JOIN ORDERसंकेत का उपयोग किए बिना अलग-अलग क्वेरी प्लान क्यों बनाते हैं ?
मैथ्यू

w / o उस संकेत को, हम JOIN ऑर्डर की गारंटी नहीं दे सकते हैं और जैसा कि आप अलग-अलग निष्पादन योजना देख रहे हैं जो यह साबित करता है। उदाहरण के लिए "सभी बाहरी का उपयोग कर" पहले तरीके में "SQL सर्वर इस दो में से कोई भी कर सकता है। पहले "MyChild + MyGrandChild" और फिर "MyParent" में शामिल हों। या पहले "MyChild + MyParent" और फिर "MyGrandChild" पर जाएं।
अनूप शाह
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.