मेरे पास एक प्रश्न है जो मुझे समस्याएं दे रहा है और मुझे समझ में नहीं आ रहा है कि क्यों MySQL का क्वेरी ऑप्टिमाइज़र इस तरह से व्यवहार कर रहा है। यहां पृष्ठभूमि की जानकारी दी गई है:MySQL इस क्वेरी को अनुकूलित क्यों नहीं कर सकता?
मेरे पास 3 टेबल हैं। दो अपेक्षाकृत छोटे हैं और एक बड़ा है।
तालिका 1 (बहुत छोटे, 727 पंक्तियाँ):
CREATE TABLE
ipa
(
ipa_id
पूर्णांक (11) नहीं NULL AUTO_INCREMENT,
ipa_code
पूर्णांक (11) डिफ़ॉल्ट शून्य,
ipa_name
varchar (100) डिफ़ॉल्ट शून्य,
payorcode
varchar (2) डिफ़ॉल्ट शून्य,
compid
पूर्णांक (11) डिफ़ॉल्ट '2'
प्राथमिक कुंजी (ipa_id
),
कुंजीipa_code
(ipa_code
)) इंजन = MyISAM
तालिका 2 (छोटा सा, 59,455 पंक्तियों):
CREATE TABLE
assign_ipa
(
assignid
पूर्णांक (11) न्यूल ऑटोमेशन,
ipa_id
int (11) न्यूल,
userid
int (11) एनयूएल नहीं एल,
username
varchar (20) डिफ़ॉल्ट शून्य,
compid
पूर्णांक (11) डिफ़ॉल्ट शून्य,
PayorCode
चार (10) डिफ़ॉल्ट शून्य
प्राथमिक कुंजी (assignid
),
अद्वितीय कुंजीassignid
(assignid
,ipa_id
),
कुंजीipa_id
(ipa_id
)
) इंजन = MyISAM
तालिका 3 (बड़े, 24,711,730 पंक्तियाँ):
क्वेरी के लिए अबटेबल बनाएं
master_final
(
IPA
पूर्णांक (11) डिफ़ॉल्ट शून्य,
MbrCt
SMALLINT (6) डिफ़ॉल्ट '0',
PayorCode
varchar (4) डिफ़ॉल्ट 'शौचालय',
कुंजीidx_IPA
(IPA
)
) इंजन = MyISAM डिफ़ॉल्ट
। मैं पहली दो छोटी तालिकाओं का उपयोग करके 3-तरफा जुड़ रहा हूं ताकि अनिवार्य रूप से बड़ी तालिका को इसके अनुक्रमित मानों में से एक पर सब्सक्राइब कर सकूं। असल में, मुझे उपयोगकर्ता, एसजेओनेस के लिए आईडी की एक सूची मिलती है और उन आईडी के लिए बड़ी फ़ाइल से पूछताछ होती है।
mysql>
बताएं मास्टर_फिनल।PayorCode, योग (master_final.Mbrct) MbrCt
रूप से master_final
अंदरूनी ipa.ipa_code पर आईपीए शामिल हों = master_final.IPA
अंदरूनी पर ipa.ipa_id = assign_ipa.ipa_id
assign_ipa शामिल हों जहां assign_ipa.username = 'SJones'
ग्रुप द्वारा master_final.PayorCode, master_final.ipa \ G;
* ** * ** * ** * ** * 1. पंक्ति * ** * ** * ** * * * *
आईडी: 1
select_type: SIMPLE
तालिका: master_final
के प्रकार: सभी
possible_keys: idx_IPA
कुंजी: शून्य
key_len: शून्य
रेफरी: शून्य
पंक्तियों:
अतिरिक्त: अस्थायी का उपयोग करना; filesort
का उपयोग * ** * ** * ** * ** * 2. पंक्ति * ** * ** * ** * ** *
आईडी: 1
SELECT_TYPE: सरल +०१२३८००७३१६ तालिका: आईपीए
प्रकार: रेफरी
possible_keys: प्राथमिक, ipa_code
कुंजी: ipa_code
key_len: 5
रेफरी: wc_test.master_final.IPA
पंक्तियों: 1
अतिरिक्त: जहां
का उपयोग करना * ** * ** * ** * ** * 3।पंक्ति * ** * ** * ** * ** *
आईडी: 1
SELECT_TYPE: सरल
तालिका: assign_ipa
प्रकार: रेफरी
possible_keys: ipa_id
कुंजी: ipa_id
key_len: 4
रेफरी: wc_test.ipa 37
अतिरिक्त:
पंक्तियों .ipa_id (! 30 मिनट की तरह) का उपयोग करते हुए जहां सेट (0.00 सेकंड) में
3 पंक्तियों
इस क्वेरी हमेशा के लिए ले जाता है। समझाया गया बयान मुझे बताता है कि, क्यों यह पूरी तरह से अच्छी अनुक्रमणिका है, भले ही यह बड़ी मेज पर एक पूर्ण टेबल स्कैन कर रहा है। यह इसका उपयोग नहीं कर रहा है। मुझे यह समझ में नहीं आता है। मैं क्वेरी देख सकता हूं और देख सकता हूं कि इसे केवल बड़ी तालिका से कुछ आईडी पूछने की आवश्यकता है। अगर मैं ऐसा कर सकता हूं, तो MySQL के अनुकूलक ऐसा क्यों नहीं कर सकते?
समझाने के लिए, यहाँ 'SJones' के साथ जुड़े आईडी हैं:
mysql> का चयन करें उपयोगकर्ता नाम, assign_ipa से जहां उपयोगकर्ता नाम = 'SJones' ipa_id;
+ ---------- + -------- +
| उपयोगकर्ता नाम | ipa_id |
+ ---------- + -------- +
| SJones | 688 |
| SJones | 68 9 |
+ ---------- + -------- +
2 सेट में पंक्तियों (0.02 सेकंड)
अब, मैं ipa_id मूल्यों प्रतिस्थापन क्वेरी पुनर्लेखन कर सकते हैं जहां खंड में उपयोगकर्ता नाम के लिए। मेरे लिए यह मूल क्वेरी के बराबर है। MySQL इसे अलग-अलग देखता है। यदि मैं ऐसा करता हूं, तो अनुकूलक बड़ी तालिका पर इंडेक्स का उपयोग करता है।
mysql> समझाने
चयन master_final.PayorCode, योग (master_final.Mbrct) MbrCt
रूप से master_final
अंदरूनी शामिल हों आईपीए पर ipa.ipa_code = master_final.IPA
अंदरूनी शामिल हों ipa.ipa_id पर assign_ipa = assign_ipa.ipa_id
* जहां'_688 ',' 68 9 ') *
ग्रुप द्वारा master_final.PayorCode, master_final.ipa \ G;
* ** * ** * ** * ** * 1।पंक्ति * ** * ** * ** * ** *
आईडी: 1
SELECT_TYPE: सरल
तालिका: आईपीए
प्रकार: सीमा
possible_keys: प्राथमिक, ipa_code
कुंजी: प्राथमिक
key_len: 4
रेफरी: NULL
पंक्तियां: 2
अतिरिक्त: कहां उपयोग करना; अस्थायी का उपयोग करना; filesort
का उपयोग * ** * ** * ** * ** * 2. पंक्ति * ** * ** * ** * ** *
आईडी: 1
SELECT_TYPE: सरल +०१२३८००७३१६ तालिका: assign_ipa
प्रकार: रेफरी
possible_keys: ipa_id
कुंजी: ipa_id
key_len: 4
रेफरी: wc_test.ipa.ipa_id
पंक्तियों: 37
अतिरिक्त: का प्रयोग जहां
* ** * ** * ** * ** * 3. पंक्ति * ** * ** * ** * ** *
आईडी: 1
SELECT_TYPE: सरल
तालिका: master_final
प्रकार: रेफरी
संभव_की: idx_IPA
कुंजी: idx_IPA
key_len: 5
रेफरी: wc_test.ipa.ipa_code
पंक्तियों:
अतिरिक्त: का प्रयोग जहां सेट में
3 पंक्तियों (0.00 सेकंड)
केवल एक चीज मैं बदल दिया है एक जहां खंड है कि बड़ी मेज भी सीधे हिट नहीं करता है। और फिर भी, अनुकूलक बड़ी तालिका पर इंडेक्स 'idx_IPA' का उपयोग करता है और पूर्ण तालिका स्कैन का अब उपयोग नहीं किया जाता है। इस तरह फिर से लिखा गया सवाल बहुत तेज़ है।
ठीक है, यह बहुत सारी पृष्ठभूमि है। अब मेरा सवाल है। अनुकूलक के लिए जहां खंड महत्वपूर्ण है? या तो जहां खंड छोटे तालिका से सेट एक ही परिणाम लौटाएगा, और फिर भी मैं जिस पर उपयोग करता हूं उसके आधार पर मुझे नाटकीय रूप से अलग-अलग परिणाम मिल रहे हैं। जाहिर है, मैं क्वेरी में सभी संबंधित आईडी को पारित करने की कोशिश करने के बजाय उपयोगकर्ता नाम वाले उपयोगकर्ता का उपयोग करना चाहता हूं। जैसा लिखा है, यह संभव नहीं है?
- क्या कोई यह समझा सकता है कि यह क्यों हो रहा है?
- पूर्ण तालिका स्कैन से बचने के लिए मैं अपनी क्वेरी को फिर से लिख सकता हूं?
मेरे साथ चिपके रहने के लिए धन्यवाद। मुझे यह एक बहुत लंबा सवाल पता है।
मैंने एक MySQL डेवलपर्स (कुछ समय पहले) द्वारा एक लेख पढ़ा था कि ऑप्टिमाइज़र अभी भी प्रगति पर एक काम था - और फिर वे ओरेकल द्वारा अवशोषित हुए थे। क्या आपने जॉइन में "संकेत" या शायद "assign_ipa.username = 'SJones'" को स्थानांतरित करने का प्रयास किया है? –