2011-09-14 3 views
9

मेरे पास दो टेबल हैं। फॉर्म ~ 77000 पंक्तियां हैं। लॉग ~ 2.7 मिलियन पंक्तियां हैं।एसक्यूएल सर्वर "<>" ऑपरेटर कुछ मिलियन पंक्तियों के साथ तालिका पर "=" की तुलना में बहुत धीमा है

निम्न क्वेरी रिटर्न "30,198" एक दूसरे से कम में:

SELECT COUNT(DISTINCT logs.DOCID) FROM logs, forms WHERE logs.DOCID = forms.DOCID; 

और इस क्वेरी ~ 15 मिनट के लिए अब तक चल रहा है, और अभी भी खत्म नहीं हुआ:

SELECT COUNT(DISTINCT logs.DOCID) FROM logs, forms WHERE logs.DOCID <> forms.DOCID; 

"बराबर नहीं" क्वेरी क्यों है तो बहुत धीमी है?

+0

'जहां लॉग नहीं हैं। DOCID = form.DOCID'' के बारे में क्या? –

+1

क्या आप 'logs.DOCID' मान ढूंढने की कोशिश कर रहे हैं जिसके लिए' फॉर्म' में कोई संबंधित मान मौजूद नहीं है?यदि ऐसा है तो 'चुनें COUNT (*) से चुनें (फॉर्म से चुनें दस्तावेज़ से चयन करें) टी' –

+0

@ मार्टिन - आपकी क्वेरी 8 सेकंड में लौटी। धन्यवाद! –

उत्तर

27

क्योंकि = प्रत्येक तालिका से एक एकल मिलान पंक्ति में शामिल होने वाले ऑपरेशन को कम करता है (मान लें कि उन डॉक्टरों को अद्वितीय माना जाता है)।

Adam  Alice 
Bob  Betty 
Charly Cathy 
Dick  Deb 
Evan  Elly 

आप उन्हें पहले अक्षर से जोड़ी: इस रास्ता आप 5 लड़के और 5 लड़कियों के साथ एक नृत्य मिल गया है इसके बारे में

Think। तो

Adam->Alice 
Bob->Betty 
etc... 

एक एकल जोड़ी

लेकिन अगर आप उनके द्वारा "सबसे पहले पत्र से मेल नहीं खाते" जोड़ी, आप के साथ अंत:

Adam->Betty 
Adam->Cathy 
Adam->Deb 
Adam->Elly 
Bob->Alice 
etc... 

तुम बड़े पैमाने पर की संख्या बढ़ा दिया है जोड़ियां। यही कारण है कि आपकी <> क्वेरी इतनी लंबी लग रही है। आप अनिवार्य रूप से min(m,n) की बजाय m x n पंक्तियां लाने की कोशिश कर रहे हैं। इस डेटा के साथ, आप 5 की बजाय 25 पंक्तियों के साथ समाप्त होते हैं। आपके निर्दिष्ट तालिका आकारों के लिए, आप 77,000 * 2,700,000 = 207.9 बिलियन पंक्तियों के साथ काम कर रहे हैं, 77,000 से कम जहां दो आईडी मिलते हैं, कुल 207,8 99, 9 23,000 पंक्तियां जुड़े डेटा सेट।

SELECT DISTINCT logs.DOCID 
FROM logs 
LEFT JOIN forms ON logs.DOCID = forms.DOCID 
WHERE forms.DOCID IS NULL 
+2

+1 मैं ओपी का अनुमान लगा रहा हूं शायद संभवत: 'IN IN' या' EXISTS' या 'EXCEPT' –

+0

धन्यवाद की आवश्यकता है! मेरी क्वेरी को अनुकूलित करने के लिए मैं कुछ भी नहीं कर सकता? मैं लॉग तालिका में किसी भी फॉर्म आईडी की तलाश में हूं जो फॉर्म तालिका में फॉर्म आईडी के अनुरूप नहीं है। मुझे लगता है कि मुझे COUNT (DISTINCT logs.formID), और COUNT (DISTINCT logs.formID) के डेल्टा को ढूंढकर उत्तर पता है, जहां logs.formID = form.formID –

+1

@ ट्रेडमैन - इस चेक के लिए 'EXISTS' या 'IN' का उपयोग करें – JNK

2

दो कारण: तुल्यता के लिए

  • प्रश्नों आम तौर पर अनुक्रमणिका उपयोग कर सकते हैं (


    आपकी क्वेरी आवश्यकताओं को देखते हुए एक छोड़ दिया में शामिल होने और अशक्त दाईं ओर रिकॉर्ड देखने की कोशिश यदि उपलब्ध हो), जबकि किसी भी योग्यता के लिए क्वेरी

  • <> इतना अधिक डेटा देता है।

<> के साथ आपकी क्वेरी फर्जी है। इसे वापस क्या करना चाहिए?

+0

प्रतिक्रिया के लिए धन्यवाद। इसे ~ 3800 वापस करना चाहिए। मैं लॉग तालिका में किसी भी फॉर्म आईडी की तलाश में हूं जो फॉर्म तालिका में फॉर्म आईडी के अनुरूप नहीं है। किसी और ने उत्तर दिया है - मुझे 'EXISTS' या' IN' का उपयोग करना चाहिए। –

+1

हां। एक और संभावना 'आईएस नूल' के साथ 'सही बाहरी जॉइन' होगी। – jpalecek

1

यह तालिका में मूल्यों के वितरण पर पूरी तरह से निर्भर है। यदि आप जिस स्तंभ को खोज रहे हैं, उदाहरण के लिए 99.99% पंक्तियों के लिए (= forms.DOCID) समान मूल्य था और एक अलग मूल्य के साथ केवल एक पंक्ति थी, तो आप वास्तव में विपरीत व्यवहार देखेंगे।

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