2015-12-05 8 views
6

के कारण 1 कॉलम सेल्फ-जॉइन पर इंडेक्स का उपयोग नहीं करता है हमारे पास एक क्वेरी है जो हमारे टेबल में से एक में डुप्लिकेट की तलाश करती है, जो पहचानकर्ता के आधार पर शायद ही उपलब्ध है, चलो इसे rareIdentifier INT(10) UNSIGNED NULL पर कॉल करें । हमारे पास इस कॉलम पर एकल कॉलम नियमित पुरानी अनुक्रमणिका है।मारियाडीबी कम चयनकता (सभी एनयूएलएल)

प्रश्न में क्वेरी इस तरह दिखता है:

SELECT a.id, b.id FROM 
    widget a INNER JOIN widget b 
ON a.rareIdentifier = b.rareIdentifier; 

समस्या यह है कि हाल ही में एक डुप्लिकेट खोजने रन के लिए, हम वास्तव में rareIdentifier के लिए एक मूल्य के साथ 0 पंक्तियों था; यानी इस पंक्ति के लिए सभी पंक्तियों में NULL था। मारिया डीबी ने Using join buffer (flat, BNL join) दृष्टिकोण का चयन करने के लिए इंडेक्स का उपयोग न करने का फैसला किया, जिसने पूरे टेबल को स्कैन किया।

लेकिन NULL एस एक दूसरे के बराबर नहीं हो सकता! तो यह पंक्तियों की प्रत्येक जोड़ी की तुलना करने की कोशिश क्यों कर रहा है?

मैं समझता हूं कि MySQL/MariaDB इंडेक्स का उपयोग नहीं करेगा यदि इसकी चयनकता बहुत कम है। मेरा मानना ​​है कि यह मामला यहां है। वास्तव में, ऐसा लगता है कि इंडेक्स में केवल 1 मान होने का मतलब है कि क्वेरी बहुत तात्कालिक है।

तालिका एक InnoDB तालिका है।

+0

उस तालिका पर आपके वर्तमान इंडेक्स क्या हैं? – Shawn

उत्तर

0

InnoDB यह समझने के लिए पर्याप्त स्मार्ट नहीं हो सकता है कि NULL की तुलना में हमेशा NULL है, इसलिए झूठी है। शायद यह तय किया गया है कि "सभी मूल्य समान हैं, इसलिए बराबर होना चाहिए" (लेकिन वास्तव में मुझे वास्तव में पता नहीं है)।

एक वर्कअराउंड के रूप में, ... AND a.rareIdentifier IS NOT NULL जोड़ने से ऑप्टिमाइज़र को संकेत मिलता है।

0

यह ज्यादातर मामलों में तेज़ हो सकता है, खासकर यदि rareIdentifier के साथ कई पंक्तियां हैं।

SELECT rareIdentifier, MIN(id), MAX(id), COUNT(*) 
    FROM tbl 
    WHERE rareIdentifier IS NOT NULL 
    GROUP BY rareIdentifier 
    HAVING COUNT(*) > 1; 

या आप मिनट & अधिकतम के बजाय GROUP_CONCAT(id) इस्तेमाल कर सकते हैं। (हालांकि, अगर dups के एक बहुत हैं, सूची काट दिया जाएगा।)

InnoDB और INDEX(rareIdentifier) मान लिया जाये कि, इस SELECT एक बहुत ही कुशल 'सीमा' सूचकांक के स्कैन किया जाना चाहिए।

अपने प्रश्न पर वापस ...

वास्तव में 0 पंक्तियों था ... MariaDB सूचकांक

मैं प्रयोग किया जाता का उपयोग नहीं करने को देखने के लिए फैसला किया है कि MySQL के पुराने संस्करणों में एक बहुत। मुझे आश्चर्य है कि ओरेकल तय है, लेकिन मारिया डीबी फिक्स चूक गया।

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