स्पष्ट बनाम निहित SQL जोड़


399

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

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;

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

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

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

3
वे अलग-अलग हैं, अंतर्निहित जुड़ाव आपको हर बार एक बार आश्चर्यचकित करेगा जब अशक्त मूल्यों से निपटना होगा; स्पष्ट जुड़ने का उपयोग करें और "कुछ भी नहीं बदला" होने पर बग से बचें!
BlackTigerX

1
इसमें कोई फर्क नही है। ,है CROSS JOINहारने बाध्यकारी और साथ INNER JOINहै CROSS JOINके साथ ONकी तरह WHERE, लेकिन बाध्यकारी तंग। निष्पादन के लिए क्या मायने रखता है कि कैसे डीबीएमएस प्रश्नों का अनुकूलन करता है।
फिलिप्पी

जवाबों:


132

प्रदर्शन के लिहाज से, वे बिल्कुल समान हैं (कम से कम SQL सर्वर में)।

पुनश्च: ध्यान रखें कि IMPLICIT OUTER JOINवाक्यविन्यास SQL ​​सर्वर 2005 के बाद से हटा दिया गया है। ( IMPLICIT INNER JOINप्रश्न में प्रयुक्त वाक्यविन्यास अभी भी समर्थित है)

"ओल्ड स्टाइल" का सिलेक्शन जॉय सिंटैक्स: केवल एक आंशिक बात है


4
@lomaxx, सिर्फ स्पष्टता के लिए, क्या आप निर्दिष्ट कर सकते हैं कि प्रश्न में 2 का कौन सा वाक्य-विन्यास हटा दिया गया है?
जे व्यानिया

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

21
आप SQL मानक को कैसे दर्शाते हैं?
डेविड क्रॉशव

7
@ दाविद क्रेंशॉ, निहित जुड़ाव अब मानक में नहीं है और 18 साल से नहीं है।
HLGEM

11
'इनर' या 'क्रॉस' किस्म के तथाकथित "निहित जोड़" मानक में बने हुए हैं। एसक्यूएल सर्वर "पुरानी शैली" के बाहरी जोड़ वाक्यविन्यास (यानी *=और =*) को चित्रित कर रहा है जो कभी भी मानक नहीं रहा है।
onedaywhen

129

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


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

56

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)

table1166208 पंक्तियाँ हैं; table2लगभग 1000 पंक्तियाँ हैं।

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


यह स्वीकृत उत्तर होना चाहिए। यह सही है, योजना एक ही है (या बड़े बयानों के करीब) लेकिन रिकॉर्ड की मात्रा बहुत अधिक हो जाएगी, इस प्रकार प्रदर्शन में अंतर पैदा होगा।
सोवियतफ्रंटियर

37

दूसरे सिंटैक्स में क्रॉस जॉइन की अवांछित संभावना होती है: आप तालिका से उसी भाग के बिना तालिका से जोड़ सकते हैं। यह हानिकारक माना जाता है।


क्या होगा यदि खंड में से तालिका के नाम, जहां खंड में प्रयुक्त तालिकाओं से उत्पन्न होते हैं?
जुस 12

आप स्पष्ट रूप से संयुक्त वाक्यविन्यास के साथ एक क्रॉस ज्वाइन भी कर सकते हैं। ( stackoverflow.com/a/44438026/929164 ) शायद आपका मतलब यह था कि यह कम सख्त है, इस प्रकार उपयोगकर्ता की त्रुटि अधिक होती है।
डैनियल डुबोव्स्की

15

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

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


5

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

मुझे लगता है कि आप पदावनत * = और = * संचालक बनाम "बाहरी जुड़ाव" के बारे में सोच रहे हैं।

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


5

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

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

विशेष रूप से, बाहरी जुड़ाव (* =) समर्थित नहीं है।


2
सच कहूँ तो मैं इसका उपयोग SQL Server 2000 में भी नहीं करूँगा, * = वाक्य रचना अक्सर गलत उत्तर देती है। कभी-कभी यह क्रॉस जॉइन के रूप में इनकी व्याख्या करता है।
एचएलजीईएम

2

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

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


1
लेह, आप निहित संकेतों में भी संकेत का उपयोग कर सकते हैं।
स्क्वायरकोग

1
ओरेकल में, निष्पादन योजना को सार्थक तरीके से प्रभावित करने के लिए सम्मिलित आदेश के लिए यह अत्यंत दुर्लभ है। विवरण के लिए जोनाथन लुईस का यह लेख देखें ।
जॉन हेलर

1

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

ओरेकल ऑप्टिमाइज़र टीम से एक पोस्टिंग

"संरचित डेटा" ब्लॉग से एक और पोस्टिंग

मुझे उम्मीद है कि आपको यह दिलचस्प लगेगा।


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

1

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


0

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

आंतरिक जुड़ावों से निपटने के दौरान न तो पठनीयता में कोई वास्तविक अंतर होता है, न ही, हालांकि, यह जटिल हो सकता है जब बाएं और दाएं जोड़ के साथ पुराने तरीके से काम करते हैं तो आपको कुछ इस तरह मिलेगा:

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

उपरोक्त पुराना तरीका है कि एक बाएं जोड़ को निम्नलिखित के विपरीत कैसे लिखा जाता है:

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

जैसा कि आप नेत्रहीन देख सकते हैं, स्क्रिप्ट कैसे लिखी जाती है इसका आधुनिक तरीका क्वेरी को अधिक पठनीय बनाता है। (वैसे ही सही जुड़ने के लिए जाता है और बाहरी जोड़ों के लिए थोड़ा अधिक जटिल है)।

बॉयलर प्लेट पर वापस जाने से, SQL कंपाइलर पर कोई फर्क नहीं पड़ता है कि क्वेरी कैसे लिखी जाती है क्योंकि यह उन्हें उसी तरह से संभालता है। मैंने ओरेकल डेटाबेस में दोनों का मिश्रण देखा है, जिसमें कई लोग लिखते हैं, दोनों बड़े और छोटे। फिर, यह उबलता है कि स्क्रिप्ट कितनी पठनीय है और जिस टीम के साथ आप विकसित कर रहे हैं।


-1

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


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