2009-06-19 10 views
131

के भीतर शर्त जॉइन क्लॉज बनाम WHERE क्लॉज में कोई शर्त लगाने के बीच कोई अंतर (प्रदर्शन, सर्वोत्तम अभ्यास, आदि ...) है?जॉइन या कहां

उदाहरण के लिए ...

-- Condition in JOIN 
SELECT * 
FROM dbo.Customers AS CUS 
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
AND CUS.FirstName = 'John' 

-- Condition in WHERE 
SELECT * 
FROM dbo.Customers AS CUS 
INNER JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
WHERE CUS.FirstName = 'John' 

कौन सा आप पसंद करते हैं (और शायद यही कारण है कि) करते हैं?

+3

क्या आपने दो प्रश्नों को चलाया? क्या आपने दो प्रश्नों से उत्पन्न निष्पादन योजनाओं की जांच की थी? आपने क्या देखा? –

+8

@ एसएलॉट, यह क्वेरी केवल उदाहरण के प्रयोजनों के लिए है। मैं बस "सामान्य में" सोच रहा हूं जो पसंदीदा तरीका है - यदि कोई है। –

+0

@ स्टेव डिग्नान: आपको इसे नमूना डेटा के साथ बेंचमार्क करना चाहिए और क्वेरी योजनाओं को देखना चाहिए। जवाब बहुत स्पष्ट होगा। और - बोनस - आपके पास कोड का एक टुकड़ा होगा जिसका आप पुन: उपयोग कर सकते हैं जब अधिक जटिल परिस्थितियां उत्पन्न होती हैं। –

उत्तर

108

संबंधपरक बीजगणित WHERE खंड में विधेय और INNER JOIN की परस्पर की अनुमति देता है, तो WHERE खंड के साथ भी INNER JOIN प्रश्नों विधेय अनुकूलक द्वारा rearrranged हो सकता है इतना है कि वे पहले से ही JOIN प्रक्रिया के दौरान बाहर रखा जा सकता है।

मैं आपको सबसे अधिक संभव तरीके से प्रश्नों को लिखने की सलाह देता हूं।

कभी-कभी इसमें INNER JOIN अपेक्षाकृत "अपूर्ण" बनाने और WHERE में कुछ मानदंडों को फ़िल्टरिंग मानदंडों की सूचियों को आसानी से बनाए रखने के लिए बस शामिल करना शामिल है।

उदाहरण के लिए

के बजाय:

SELECT * 
FROM Customers c 
INNER JOIN CustomerAccounts ca 
    ON ca.CustomerID = c.CustomerID 
    AND c.State = 'NY' 
INNER JOIN Accounts a 
    ON ca.AccountID = a.AccountID 
    AND a.Status = 1 

लिखें:

SELECT * 
FROM Customers c 
INNER JOIN CustomerAccounts ca 
    ON ca.CustomerID = c.CustomerID 
INNER JOIN Accounts a 
    ON ca.AccountID = a.AccountID 
WHERE c.State = 'NY' 
    AND a.Status = 1 

लेकिन यह निश्चित रूप से, निर्भर करता है।

+13

इसे जोड़ने के लिए ऊपर निर्भर करता है। बेंचमार्क सब कुछ। – marr75

+2

यह केवल स्वच्छ क्वेरी या पठनीयता के बारे में नहीं है, यह प्रदर्शन के बारे में है।सही ढंग से अनुक्रमित तालिकाओं के साथ बड़ी मात्रा में डेटा के प्रदर्शन में सुधार करने के लिए स्थितियों को शामिल करना। – Shahdat

+0

@ शाहदत ने कभी निष्पादन योजना नहीं देखी, जहां –

7

जॉइन होने के बाद फ़िल्टर करेगा।

जॉइन प्रक्रिया के दौरान पंक्तियों को जोड़ने से रोकने के लिए जॉइन पर फ़िल्टर करें।

+8

अर्थात्, इन्हें इनर जॉइन प्रक्रिया के दौरान रोका जाता है, लेकिन ऑप्टिमाइज़र इनर जॉइन को पुनर्व्यवस्थित कर सकता है और जहां इच्छा पर भविष्यवाणी की जाती है, तो ऑप्टिमाइज़र बाद में उन्हें बाहर करने के लिए स्वतंत्र होता है यदि वह चाहें। –

+1

कैड रॉक्स: दाएं। एसक्यूएल में जो भी बार आप लिखते हैं वह वही नहीं है जब ऑप्टिमाइज़र आपको बताएगा और पूरा किया जाएगा। मुझे लगता है कि यह एक अखिल सिद्धांत दुनिया में सही होगा, जबकि आपका उत्तर स्वचालित क्वेरी ऑप्टिमाइज़र की दुनिया में अधिक सही है :) – TheTXI

3

मैं पूर्ण तालिकाओं/दृश्यों में शामिल होने के लिए जॉइन पसंद करता हूं और फिर परिणामस्वरूप सेट के पूर्वानुमान को पेश करने के लिए कहां उपयोग करता हूं।

यह वाक्य रचनात्मक रूप से क्लीनर लगता है।

0

शामिल होने की स्थिति को रखना मेरे लिए "अर्थात् गलत" लगता है, क्योंकि यह नहीं है कि जॉइन "के लिए" हैं। लेकिन यह बहुत गुणात्मक है।

अतिरिक्त समस्या: यदि आप किसी भी आंतरिक जुड़ने से स्विच करने का निर्णय लेते हैं, तो कहें, सही जुड़ाव, जॉइन के अंदर स्थिति होने से अप्रत्याशित परिणाम हो सकते हैं।

+3

कभी-कभी ये परिणाम थोड़े "अपेक्षित" होते हैं और कभी-कभी "जानबूझकर" (के लिए बाहरी जुड़ने के साथ उदाहरण, जहां जॉइन हालत की तुलना में जहां हालत की अलग-अलग अर्थशास्त्र है)। – Thetam

20

अधिकांश आरडीबीएमएस उत्पाद दोनों प्रश्नों को समान रूप से अनुकूलित करेंगे। पीटर गुलुटान और ट्रूडी पेलज़र द्वारा "एसक्यूएल प्रदर्शन ट्यूनिंग" में, उन्होंने आरडीबीएमएस के कई ब्रांडों का परीक्षण किया और कोई प्रदर्शन अंतर नहीं मिला।

मैं क्वेरी प्रतिबंध शर्तों से अलग स्थितियों को शामिल रखना पसंद करता हूं।

यदि आप OUTER JOIN का उपयोग कर रहे हैं तो कभी-कभी इसमें शामिल होने वाले खंड में शर्तों को रखना आवश्यक है।

+1

मैं आपसे सहमत हूं कि वाक्य रचनात्मक रूप से यह क्लीनर है, और मुझे उस पुस्तक और आपकी बहुत प्रतिष्ठा के बारे में आपके ज्ञान को स्थगित करना होगा, लेकिन मैं पिछले सप्ताह में 4 अलग-अलग निष्पादन योजनाओं, सीपीयू टाइम्स और लॉजिकल रीड के साथ 4 प्रश्नों के बारे में सोच सकता हूं जब मैं चले गए जहां शामिल होने की भविष्यवाणी की गई। – marr75

+1

आप सर्वोत्तम प्रथाओं के बारे में पूछ रहे थे। जैसे ही आप परीक्षण करते हैं कि एक विशिष्ट आरडीबीएमएस कार्यान्वयन कैसे काम करता है, अन्य लोगों ने सही सलाह दी है: बेंचमार्क। –

2

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

जब कोई अपना एसक्यूएल बेंचमार्किंग दिखाता है तो मैं हमेशा हल्के से खुश हूं और उन्होंने देव सर्वर पर मध्यरात्रि में 50,000 बार स्प्राक के दोनों संस्करणों को निष्पादित किया है और औसत समय की तुलना की है।

0

जब आपके पास बड़ी तालिका होती है तो जॉइन मेरी राय में तेज़ी से होते हैं। यह वास्तव में इतना अंतर नहीं है कि विशेष रूप से यदि आप एक छोटी सी तालिका से निपट रहे हैं। जब मैंने पहली बार शामिल होने के बारे में सीखा, तो मुझे बताया गया कि जुड़ने की स्थितियां केवल क्लॉज की स्थितियों की तरह हैं और अगर मैं इस तालिका को किस स्थिति के बारे में बताता हूं तो यह कहां अलग-अलग उपयोग कर सकता है।

82

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

हालांकि यदि आप बाएं या दाएं जुड़ने का उपयोग कर रहे हैं तो हालात कहां डालते हैं तो यह एक बड़ा अंतर बनाता है। मिसाल के तौर पर इन दो प्रश्नों पर विचार करें:

SELECT * 
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
WHERE ORD.OrderDate >'20090515' 

SELECT * 
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
AND ORD.OrderDate >'20090515' 

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

SELECT * 
FROM dbo.Customers AS CUS 
LEFT JOIN dbo.Orders AS ORD 
ON CUS.CustomerID = ORD.CustomerID 
WHERE ORD.OrderID is null 
+0

उदाहरणों के साथ समझाए जाने के लिए धन्यवाद –

+0

महान उत्तर - ओपी के लिए स्पष्ट और प्रासंगिक – psrpsrpsr

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