2008-09-04 7 views
311

में स्पष्ट रूप से अंतर्निहित आंतरिक शामिल होने में कोई दक्षता अंतर है? उदाहरण के लिए:स्पष्ट बनाम अंतर्निहित एसक्यूएल

SELECT * FROM 
table a INNER JOIN table b 
ON a.id = b.id; 

बनाम

SELECT a.*, b.* 
FROM table a, table b 
WHERE a.id = b.id; 
+7

अच्छा सवाल। मैं उत्सुक हूं कि स्पष्ट रूप से शामिल होने का उपयोग क्यों किया जाता है। क्या इसके बिना सभी प्रश्न पूछना संभव नहीं है? – andrew

+4

उपयोग व्याख्या कीवर्ड दोनों प्रश्नों के बारे में अंतर जानना .. का उपयोग शामिल हों और अंतर देखेंगे .. आप एक से अधिक 100k रिकॉर्ड किसी तालिका में प्रयास करते हैं तो आप अंतर ... –

+0

देख सकते हैं @andrew मेरा प्रश्न वास्तव में था निहित में शामिल होने के लिए कि क्या "हैक" का एक रूप था (जैसा कि "एक से अधिक तालिका से जुड़ी एक क्वेरी, शामिल होने का उपयोग नहीं कर रही है? यह एक हैक है ना?") – bobobobo

उत्तर

101

प्रदर्शन बुद्धिमान, वे ठीक उसी (कम से कम एसक्यूएल सर्वर में) कर रहे हैं।

पुनश्च: ध्यान रखें कि IMPLICIT OUTER JOIN वाक्य रचना एसक्यूएल सर्वर 2005 (IMPLICIT INNER JOIN वाक्य रचना के रूप में प्रश्न में इस्तेमाल अभी भी समर्थित है)

Deprecation of "Old Style" JOIN Syntax: Only A Partial Thing

+0

निहित शामिल वाक्यविन्यास SQL ​​सर्वर 2005 द्वारा बॉक्स के बाहर समर्थित है, लेकिन हाँ, यह एक बुरा विचार है। –

+1

हालांकि मैं स्पष्ट वाक्यविन्यास पसंद करता हूं, क्या आप समझा सकते हैं कि वे अंतर्निहित जोड़ों को कैसे हटा सकते हैं? यह विचार कि इसे बहिष्कृत किया जा सकता है, अजीब लगता है और सुझाव है कि वे SQL 2K5 द्वारा समर्थित नहीं हैं, यह सही नहीं है। – BlackWasp

+7

क्या आप सहायक दस्तावेज प्रदान कर सकते हैं? यह कई स्तरों पर गलत लगता है। – NotMe

110

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

+0

मैं पूरी तरह से सहमत हूं, लेकिन यह ऑफ-विषय है। ओपी ने दक्षता के बारे में पूछा। – VillasV

4

प्रदर्शन के अनुसार, वे बिल्कुल वही हैं (कम से कम SQL सर्वर में) लेकिन ध्यान रखें कि वे इस वाक्यविन्यास में शामिल हो रहे हैं और यह बॉक्स के बाहर SQL सर्वर 2005 द्वारा समर्थित नहीं है।

मुझे लगता है कि आप बहिष्कृत * = और = * ऑपरेटरों बनाम "बाहरी शामिल" के बारे में सोच रहे हैं।

मैंने अभी दो प्रारूपों का परीक्षण किया है, और वे SQL सर्वर 2008 डेटाबेस पर ठीक से काम करते हैं। मेरे मामले में उन्होंने समान निष्पादन योजनाएं उत्पन्न कीं, लेकिन मैं आत्मविश्वास से यह नहीं कह सकता कि यह हमेशा सत्य होगा।

2

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

आपने यह निर्दिष्ट नहीं किया कि आप किस डेटाबेस का उपयोग कर रहे हैं, लेकिन संभावना SQL सर्वर या MySQL सुझाती है जहां यह कोई वास्तविक अंतर नहीं बनाता है।

+1

लेघ, आप अंतर्निहित जोड़ों में भी संकेतों का उपयोग कर सकते हैं। – SquareCog

+1

ओरेकल में निष्पादन योजना को सार्थक तरीके से प्रभावित करने के लिए शामिल होने के लिए यह बेहद दुर्लभ है। जोनाथन लुईस ने स्पष्टीकरण के लिए [यह आलेख] देखें (http://jonathanlewis.wordpress.com/2006/11/03/table-order/)। –

6

@lomaxx: बस स्पष्ट करने के लिए, मैं बहुत कुछ है कि दोनों वाक्य रचना के ऊपर एसक्यूएल सर्व 2005 के द्वारा समर्थित हैं नीचे वाक्य रचना हालांकि समर्थित नहीं है

select a.*, b.* 
from table a, table b 
where a.id *= b.id; 

विशेष रूप से, कर रहा हूँ बाहरी में शामिल होने के (* =) समर्थित नहीं है।

+1

स्पष्ट रूप से मैं इसे SQL Server 2000 में भी उपयोग नहीं करता, * = वाक्यविन्यास अक्सर गलत जवाब देता है। कभी-कभी यह इन्हें क्रॉस जॉइन के रूप में व्याख्या करता है। – HLGEM

14

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

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

1

जैसा कि लेघ कैल्डवेल ने कहा है, क्वेरी ऑप्टिमाइज़र एक ही SQL कथन की तरह दिखने के आधार पर विभिन्न क्वेरी योजनाएं उत्पन्न कर सकता है।आगे इस पर पढ़ने के लिए, निम्न दो ब्लॉग पोस्टिंग पर एक नजर है: -

One posting from the Oracle Optimizer Team

Another posting from the "Structured Data" blog

मैं आप इस दिलचस्प उम्मीद है।

+0

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

31

दूसरे वाक्यविन्यास में क्रॉस में शामिल होने की अनचाहे संभावना है: आप बिना किसी WHERE खंड के FROM भाग में तालिकाओं को जोड़ सकते हैं। यह हानिकारक माना जाता है।

+0

क्या होगा यदि क्लॉज में तालिका नाम खंड में उपयोग की जाने वाली तालिकाओं से उत्पन्न होते हैं? – Jus12

1

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

38

MySQL 5.1.51 को दोनों प्रश्नों समान निष्पादन योजना है:

mysql> explain select * from table1 a inner join table2 b on a.pid = b.pid; 
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref   | rows | Extra | 
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+ 
| 1 | SIMPLE  | b  | ALL | PRIMARY  | NULL | NULL | NULL   | 986 |  | 
| 1 | SIMPLE  | a  | ref | pid   | pid | 4  | schema.b.pid | 70 |  | 
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+ 
2 rows in set (0.02 sec) 

mysql> explain select * from table1 a, table2 b where a.pid = b.pid; 
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+ 
| id | select_type | table | type | possible_keys | key | key_len | ref   | rows | Extra | 
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+ 
| 1 | SIMPLE  | b  | ALL | PRIMARY  | NULL | NULL | NULL   | 986 |  | 
| 1 | SIMPLE  | a  | ref | pid   | pid | 4  | schema.b.pid | 70 |  | 
+----+-------------+-------+------+---------------+------+---------+--------------+------+-------+ 
2 rows in set (0.00 sec) 

table1 166208 पंक्तियां हैं; table2 में लगभग 1000 पंक्तियां हैं।

यह एक बहुत ही साधारण मामला है; यह किसी भी माध्यम से साबित नहीं करता है कि क्वेरी ऑप्टिमाइज़र भ्रमित नहीं होगा और एक और जटिल मामले में अलग-अलग योजनाएं उत्पन्न करेगा।

0

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

+2

क्या आपके पास इसका कोई सबूत है? क्योंकि [स्वीकृत उत्तर] (http://stackoverflow.com/a/44932/1652962) अन्यथा कहता है। – cimmanon