क्या अधिक कुशल है, जहां एक खंड या लाख से अधिक पंक्ति तालिकाओं के साथ जुड़ना है?


17

हम एक वेबसाइट चलाते हैं जिसमें एक तालिका में 250MM पंक्तियाँ होती हैं और दूसरी तालिका में जो हम इसमें शामिल होते हैं वह अधिकांश प्रश्नों के लिए सिर्फ 15MM पंक्तियों के अंतर्गत होती है।

नमूना संरचनाएं:

MasterTable (Id, UserId, Created, Updated...) -- 15MM Rows
DetailsTable (Id, MasterId, SomeColumn...) -- 250MM Rows
UserTable (Id, Role, Created, UserName...) -- 12K Rows

हमें नियमित रूप से इन सभी तालिकाओं के खिलाफ कुछ प्रश्न करने होंगे। एक मुफ्त उपयोगकर्ताओं (~ 10k मुक्त उपयोगकर्ताओं) के लिए आंकड़े हड़प रहा है।

Select Count(1) from DetailsTable dt 
join MasterTable mt on mt.Id = dt.MasterId 
join UserTable ut on ut.Id = mt.UserId 
where ut.Role is null and mt.created between @date1 and @date2

समस्या यह है कि यह प्रश्न इस तथ्य के कारण होगा कि जॉन्स लंबे समय से बहुत लंबे समय से चल रहे हैं।

इस मामले में यह जुड़ाव या संभवतः के बजाय wheres का उपयोग करने के लिए समझदार होगा where column in(...)?


1
क्या डेटाबेस और संस्करण?
Leigh Riffel

2
क्या आपने दोनों तरह से कोशिश की है?
gbn

यदि यह ओरेकल था, तो मैं NVT2 (रोल, NULL, ID) पर UserTable के लिए एक फंक्शन आधारित इंडेक्स बनाऊंगा, लेकिन यह दूसरे DB जैसा दिखता है।
लेह रिफ़ेल

जवाबों:


20

आधुनिक RDBMS के लिए "स्पष्ट JOIN" और "JOIN-in-WHERE" के बीच कोई अंतर नहीं है (यदि सभी JOINS INNER हैं) प्रदर्शन और क्वेरी योजना का संबंध है।

स्पष्ट जॉय सिंटैक्स स्पष्ट और कम अस्पष्ट है (नीचे लिंक देखें)

अब, JOIN- पहले-जहाँ तार्किक प्रसंस्करण वास्तविक प्रसंस्करण नहीं है और आधुनिक ऑप्टिमाइज़र इसे महसूस करने के लिए पर्याप्त चतुर हैं।

यहां आपकी समस्या सबसे अधिक संभावना है।

कृपया हमें इन तालिकाओं पर सभी अनुक्रमित और कुंजियाँ दिखाएं। और क्वेरी की योजना है

नोट: यह प्रश्न अब तक डुप्लिकेट होने के लिए StackOverflow पर बंद हो गया होगा ... COUNT (1) बनाम COUNT (*) एक और पर्दाफाश मिथक भी है।


2
यह हमेशा सच नहीं है कि joinऔर whereखंड के बीच कोई अंतर नहीं है । मैं हर समय लंबे समय तक चलने वाले प्रश्नों का अनुकूलन करता हूं और कभी-कभी whereक्लॉज का उपयोग करने वाले प्रश्न join70x तक के कारक के उपयोग से बेहतर प्रदर्शन करते हैं । यदि यह सरल और सीधा होता, तो जीवन सभी इंद्रधनुष और गेंडा होता। और यह कुछ प्राचीन अस्पष्ट इंजन के बारे में नहीं है - अभी मैं whereएसक्यूएल 2012 में खंड के 70x लाभ को देख रहा हूं ।
अजेह

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

3
@ हजेह: मैं सुझाव दूंगा कि आपका अनुभव बहुत ही अनपेक्षित है। यदि आपके पास x70 अंतर हैं, तो आपके पास प्रश्नों के साथ बड़े मुद्दे हैं: यह है कि सरल
gbn

5

आपको क्वेरी को पूरी तरह से रिफलेक्टर करना होगा

WHERE क्लॉस पहले और जिन्न बाद में परफॉर्म करने की कोशिश करें

Select Count(1) from DetailsTable dt
join (Select UserId,Id FROM MasterTable where
created between @date1 and @date2) mt on mt.Id = dt.MasterId 
join (Select Id FROM UserTable WHERE Role is NULL) ut
on ut.Id = mt.UserId;

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

मुझे यह विचार इस YouTube वीडियो से मिला

मैंने स्टैकऑवरफ्लो में एक बहुत ही जटिल प्रश्न में वीडियो से सिद्धांतों की कोशिश की और 200 अंक का इनाम मिला।

@ आपने यह सुनिश्चित करने का उल्लेख किया है कि आपके पास सही सूचकांक हैं। इस स्थिति में, कृपया बनाए गए कॉलम को मास्टरटेबल में अनुक्रमित करें।

कोशिश करो !!!

UPDATE 2011-06-24 22:31 EDT

आपको इन प्रश्नों को चलाना चाहिए:

SELECT COUNT(1) AllRoles FROM UserTable;
SELECT COUNT(1) NullRoles FROM UserTable WHERE Role is NULL;

यदि NullRoles X 20 <AllRoles (दूसरे शब्दों में, यदि NullRoles कम है, तो तालिका पंक्तियों का 5%), आपको UserTable में एक गैर-अद्वितीय सूचकांक भूमिका बनाना चाहिए। अन्यथा, UserTable की एक पूरी तालिका पर्याप्त होगी क्योंकि क्वेरी ऑप्टिमाइज़र संभवतः एक इंडेक्स का उपयोग करके शासन कर सकता है।

UPDATE 2011-06-25 12:40 EDT

चूंकि मैं एक MySQL DBA हूं, इसलिए मेरे काम करने के तरीके में सकारात्मक निराशावाद के माध्यम से MySQL क्वेरी ऑप्टिमाइज़र पर भरोसा करने और रूढ़िवादी होने की आवश्यकता नहीं है। इस प्रकार, मैं MySQL क्वेरी ऑप्टिमाइज़र की छिपी हुई बुरी आदतों से आगे निकलने के लिए एक क्वेरी को रीक्रिएट करने या आवश्यक कवरिंग इंडेक्स बनाने की कोशिश करूँगा। @ gbn का उत्तर अधिक पूर्ण लगता है कि SQL सर्वर में प्रश्नों का मूल्यांकन करने के लिए "मन की ध्वनि" अधिक हो सकती है।


0

हमारे पास 75 मीटर पंक्तियों के बारे में एक [विवरण] तालिका थी; [मास्टर] 400K पंक्तियों के बारे में तालिका और संबंधित [आइटम] तालिका जिसमें 7 पंक्तियाँ थीं - हमेशा और हमेशा के लिए। इसने "आइटम नंबर्स" (1-7) के छोटे सेट को संग्रहीत किया और एक कागज़ के रूप में मॉडलिंग कर रहा था, जिसमें से हर महीने लाखों मुद्रित और वितरित किए जाते थे। सबसे तेज क्वेरी वह थी जिसके बारे में आप कम से कम पहले सोचते थे, जिसमें कार्टेशियन जॉइन का उपयोग शामिल था। IIRC, यह कुछ इस तरह था:

SELECT m.order_id, i.line_nr, d.Item_amt
FROM Master m, Item i 
INNER JOIN Detail d ON m.order_id = d.order_id

भले ही [आइटम] और [विवरण] के बीच एक तार्किक "आईडी" लिंक है, क्रोस जॉइनर ने इनर जॉइन से बेहतर काम किया।

RDBMS अपनी MPP तकनीक के साथ Teradata था, और IDR सूचकांक योजना क्या थी। 7 पंक्ति तालिका में कोई सूचकांक नहीं था क्योंकि टेबल स्कैन हमेशा सबसे अच्छा प्रदर्शन करता था।

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