मुझे पता है कि मैं FORCE INDEX (abc)
कीवर्ड का उपयोग करके MySQL क्वेरी को निष्पादित करने का तरीका बदल सकता हूं। लेकिन निष्पादन आदेश बदलने का कोई तरीका है?क्या MySQL निष्पादन आदेश को बल देने का कोई तरीका है?
मेरे क्वेरी इस तरह दिखता है:
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
AND c.itemid = 123456
मैं हर संबंध/बाधा है कि मैं का उपयोग के लिए एक महत्वपूर्ण है। अगर मैं इस कथन पर समझाता हूं तो मुझे लगता है कि mysql पहले c से पूछताछ शुरू करता है।
id select_type table type
1 SIMPLE c ref
2 SIMPLE b ref
3 SIMPLE a eq_ref
हालांकि, मैं जानता हूँ कि आदेश a -> b -> c
तेजी से किया जाएगा में से क्वेरी (मैं सिद्ध कर दिया है कि) कि वहाँ एक रास्ता एक विशेष क्रम का उपयोग करने के mysql बताने के लिए है?
अद्यतन: इस तरह मुझे पता है कि a -> b -> c
तेज है।
उपर्युक्त क्वेरी को पूरा करने और 7 पंक्तियों को वापस करने के लिए 1.9 सेकंड लगते हैं। यदि मैं क्वेरी को
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
HAVING c.itemid = 123456
क्वेरी 0.01 सेकंड में पूर्ण हो जाती है (मुझे 10.000 पंक्तियां प्राप्त करने के बिना)। हालांकि यह एक सुरुचिपूर्ण समाधान नहीं है क्योंकि यह क्वेरी एक सरलीकृत उदाहरण है। असली दुनिया में मैं सी से दूसरे टेबल में शामिल हो गया हूं। चूंकि HAVING
एक फ़िल्टर है जो पूरे परिणाम पर निष्पादित किया जाता है, इसका मतलब यह होगा कि मैं कुछ आवर्धन को डीबी से अनावश्यक से अधिक रिकॉर्ड खींचूंगा।
EDIT2: बस कुछ जानकारी:
- इस क्वेरी में चर हिस्सा c.itemid है। बाकी सब कुछ निश्चित मान हैं जो नहीं बदलते हैं।
- इंडेक्स सेटअप ठीक हैं और mysql
-
ए और बी के बीच
- मेरे लिए सही लोगों को चुनता है एक 1: n संबंध (सूचकांक प्राथमिक प्रयोग किया जाता है) ख के बीच
- और सी एक कई कई लोगों के लिए नहीं है संबंध (सूचकांक IDX_ITEMID प्रयोग किया जाता है)
मुद्दा यह है कि mysql तालिका एक क्वेरी करने शुरू कर देना चाहिए और यह रास्ता ग करने के लिए नीचे और नहीं इसका उल्टा है काम करते हैं। उसको प्राप्त करने के लिए कोई भी परिवर्तन।
समाधान: मैं नहीं वास्तव में क्या चाहता था, लेकिन यह काम करने के लिए लगता है:
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
AND c.itemid = 123456
AND f.id IN (
SELECT DISTINCT table2.id FROM table1
INNER JOIN table2 ON table1.id = table2.table1_id
WHERE table1.itemtype = 1 AND table1.busy = 1)
आपने कैसे साबित किया है कि 'ए -> बी -> सी' तेज होगा? इसके अलावा, क्या आप अपनी अनुक्रमणिका दिखा सकते हैं? – Unreason
परीक्षण के लिए जो तेज़ी से है, परीक्षण करना मुश्किल हो सकता है कि वास्तव में बड़ी मात्रा में डेटा पूर्व लोड और सामान्य भार को अनुकरण करने के बिना। MySQL को अपना स्वयं का अनुकूलन करने देना अक्सर अच्छा होता है, जो आपके पास जितना अधिक डेटा होता है (और समय के साथ, या एक बार या दो बार विश्लेषण तालिका), और यदि आप समस्याओं में भाग लेते हैं तो केवल सूचकांक को बल देते हैं। हालांकि ऐसी समस्याएं मौजूद हैं; मेरे पास निश्चित रूप से ऐसी स्थितियां थीं जहां MySQL की क्वेरी योजना खतरनाक रूप से खराब थी लेकिन एक निश्चित अनुक्रमणिका को मजबूर करने के बाद और इसलिए आदेश में शामिल होने से यह अच्छा और कुशलतापूर्वक काम करता था। – thomasrutter
@thomasrutter: अगर एक 2-7 सेकंड में MySQL के अनुकूलन परिणाम (लोड पर निर्भर करता है डेटा के/राशि) क्वेरी मैं अपने खुद के अनुकूलन का उपयोग कर के रूप में :) Hammerite सुझाव के अलावा कोई अन्य choise है: STRAIGHT_JOIN जो मैं चाहता करता है और 1 क्वेरी बांधा एक हजार गुणा। –