अपना EXPLAIN
देख रहे हैं आउटपुट, मैं चिंतित था कि आपके उपश्रेणियों के उपयोग के परिणामस्वरूप अनुक्रमणिका का उप-उपयोग किया गया था। मैंने महसूस किया (बिना किसी औचित्य के - और इस पर मैं बहुत गलत हो सकता हूं) कि JOIN
का उपयोग करके पुनर्लेखन अधिक अनुकूलित क्वेरी का कारण बन सकता है।
ऐसा करने के लिए, हमें यह समझने की जरूरत है कि आपकी क्वेरी क्या करने का इरादा रखती है। यदि आपके प्रश्न ने इसे स्पष्ट कर दिया होता तो इससे मदद मिलती, लेकिन थोड़ा सिर खुजलाने के बाद मैंने फैसला किया कि आपकी क्वेरी किसी भी लेख में दिखाई देने वाले अन्य सभी कीवर्ड की एक सूची लाने की कोशिश कर रही है जिसमें कुछ दिए गए कीवर्ड शामिल हैं, एक गिनती के साथ उन सभी लेखों में से जिनमें वे कीवर्ड दिखाई देते हैं ।
अब क्वेरी को चरणों में फिर से बनाते हैं:
-
"कोई भी लेख प्राप्त करें जिसमें कुछ दिए गए कीवर्ड हों " (डुप्लिकेट के बारे में चिंता न करें):
SELECT ca2.article_id FROM career_article_keyword AS ca2 WHERE ca2.keyword_id = 9;
-
"[उपरोक्त] में प्रकट होने वाले अन्य सभी कीवर्ड्स को प्राप्त करें "
SELECT ca1.keyword_id FROM career_article_keyword AS ca1 JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id) WHERE ca1.keyword_id <> 9 AND ca2.keyword_id = 9 GROUP BY ca1.keyword_id;
-
"[उपरोक्त] प्राप्त करें, साथ ही उन सभी लेखों की गिनती करें जिनमें वे कीवर्ड दिखाई देते हैं "
SELECT ca1.keyword_id, COUNT(DISTINCT ca0.article_id) AS cnt FROM career_article_keyword AS ca0 JOIN career_article_keyword AS ca1 USING (keyword_id) JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id) WHERE ca1.keyword_id <> 9 AND ca2.keyword_id = 9 GROUP BY ca1.keyword_id ORDER BY cnt DESC;
-
अंत में, हम आउटपुट में मिलान करने वाले कीवर्ड को
career_keyword
. से जोड़ना चाहते हैं टेबल:SELECT ck.keyword_id, ck.keyword, COUNT(DISTINCT ca0.article_id) AS cnt FROM career_keywords AS ck JOIN career_article_keyword AS ca0 USING (keyword_id) JOIN career_article_keyword AS ca1 USING (keyword_id) JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id) WHERE ca1.keyword_id <> 9 AND ca2.keyword_id = 9 GROUP BY ck.keyword_id -- equal to ca1.keyword_id due to join conditions ORDER BY cnt DESC;
एक बात जो तुरंत स्पष्ट हो जाती है, वह यह है कि आपकी मूल क्वेरी career_keywords
. का संदर्भ देती है दो बार, जबकि यह फिर से लिखी गई क्वेरी उस तालिका को केवल एक बार संदर्भित करती है; यह अकेले प्रदर्शन अंतर की व्याख्या कर सकता है - इसके दूसरे संदर्भ को हटाने का प्रयास करें (यानी जहां यह आपकी पहली सबक्वायरी में दिखाई देता है), क्योंकि यह वहां पूरी तरह से बेमानी है।
इस क्वेरी पर पीछे मुड़कर देखने पर, हम देख सकते हैं कि जॉइन निम्न कॉलमों पर किया जा रहा है:
-
career_keywords.keyword_id
ck JOIN ca0
यह तालिका
PRIMARY KEY (`keyword_id`)
. को परिभाषित करती है , इसलिए एक अच्छी अनुक्रमणिका है जिसका उपयोग इस जुड़ाव के लिए किया जा सकता है। -
career_article_keyword.article_id
ca1 JOIN ca2
यह तालिका
UNIQUE KEY `article_id` (`article_id`,`keyword_id`)
को परिभाषित करती है और, चूंकिarticle_id
इस इंडेक्स में सबसे बाईं ओर का कॉलम है, एक अच्छा इंडेक्स है जिसका इस्तेमाल इस जॉइन के लिए किया जा सकता है। -
career_article_keyword.keyword_id
ck JOIN ca0
औरca0 JOIN ca1
कोई अनुक्रमणिका नहीं है जिसका उपयोग इस जुड़ाव के लिए किया जा सकता है:इस तालिका में परिभाषित एकमात्र अनुक्रमणिका में एक और कॉलम है,
article_id
keyword_id
. के बाईं ओर - इसलिए MySQL कोkeyword_id
नहीं मिल रहा है पहलेarticle_id
. को जाने बिना अनुक्रमणिका में प्रविष्टियां . मेरा सुझाव है कि आप एक नई अनुक्रमणिका बनाएं जिसमेंkeyword_id
. हो इसके सबसे बाएं कॉलम के रूप में।(इस इंडेक्स की आवश्यकता को सीधे आपकी मूल क्वेरी को देखकर पता लगाया जा सकता है, जहां आपके दो सबसे बाहरी प्रश्न उस कॉलम में जुड़ते हैं।)