2009-04-07 18 views
18

का उपयोग करते समय मैं अपने SQL-code में "ORDER BY" -statements के उपयोग के कारण कुछ प्रमुख प्रदर्शन मुद्दों को मार रहा हूं।MySQL इंडेक्स का उपयोग नहीं कर रहा है ("फाइलों का उपयोग करना") ORDER BY

सब कुछ ठीक है जब तक मैं SQL में ORDER BY-statement का उपयोग नहीं कर रहा हूं। हालांकि, एक बार जब मैं ORDER BY: एसक्यूएल कोड में प्रस्तुत करता हूं तो सही इंडेक्सिंग की कमी के कारण सब कुछ नाटकीय रूप से धीमा हो जाता है। कोई यह मान लेगा कि यह तय करना मामूली होगा, लेकिन फोरम चर्चाओं से निर्णय लेना आदि यह एक आम मुद्दा है कि मुझे अभी तक इस प्रश्न का एक निश्चित और संक्षिप्त उत्तर नहीं मिला है।

प्रश्न: को देखते हुए निम्न तालिका ...

 
CREATE TABLE values_table (
    id int(11) NOT NULL auto_increment, 
    ... 
    value1 int(10) unsigned NOT NULL default '0', 
    value2 int(11) NOT NULL default '0', 
    PRIMARY KEY (id), 
    KEY value1 (value1), 
    KEY value2 (value2), 
) ENGINE=MyISAM AUTO_INCREMENT=2364641 DEFAULT CHARSET=utf8; 

... कैसे मैं अनुक्रमित है कि जब एक मान 1 -range के लिए तालिका में जानना चाहते हैं, जबकि मूल्य के वर्गीकरण का उपयोग किया जाएगा बना सकता हूँ मूल्य 2?

वर्तमान में, ऑर्डर द्वारा ऑर्डर द्वारा उपयोग नहीं किया जा रहा है, तो वर्तमान में लांचिंग ठीक है।

निम्नलिखित व्याख्या क्वेरी के उत्पादन देखें:

 
OK, when NOT using ORDER BY: 

EXPLAIN select ... from values_table this_ where this_.value1 between 12345678 and 12349999 limit 10; 

+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ 
| 1 | SIMPLE  | this_ | range | value1  | value1 | 4  | NULL | 3303 | Using where | 
+----+-------------+-------+-------+---------------+----------+---------+------+------+-------------+ 
 
However, when using ORDER BY I get "Using filesort": 

EXPLAIN select ... from values_table this_ where this_.value1 between 12345678 and 12349999 order by this_.value2 asc limit 10; 

+----+-------------+-------+-------+---------------+----------+---------+------+------+-----------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | Extra      | 
+----+-------------+-------+-------+---------------+----------+---------+------+------+-----------------------------+ 
| 1 | SIMPLE  | this_ | range | value1  | value1 | 4  | NULL | 3303 | Using where; Using filesort | 
+----+-------------+-------+-------+---------------+----------+---------+------+------+-----------------------------+ 

तालिका सामग्री के बारे में कुछ अतिरिक्त जानकारी:

 
SELECT MIN(value1), MAX(value1) FROM values_table; 
+---------------+---------------+ 
| MIN(value1) | MAX(value2) | 
+---------------+---------------+ 
|    0 | 4294967295 | 
+---------------+---------------+ 

... 

SELECT MIN(value2), MAX(value2) FROM values_table; 
+---------------+---------------+ 
| MIN(value2) | MAX(value2) | 
+---------------+---------------+ 
|    1 |  953359 | 
+---------------+---------------+ 

कृपया मुझे पता कोई और जानकारी सवाल का जवाब देने की जरूरत है, तो चलो ।

बहुत पहले से धन्यवाद!

# अद्यतन 1: एक नई समग्र सूचकांक जोड़ना (ALTER तालिका values_table सूचकांक (मान 1, मान 2 ADD);) समस्या का समाधान नहीं है। ऐसी इंडेक्स जोड़ने के बाद भी आपको "फाइलों का उपयोग करना" मिल जाएगा।

अद्यतन # 2: एक बाधा है कि मैं अपने प्रश्न में उल्लेख नहीं था कि मैं नहीं बल्कि इस्तेमाल किया एसक्यूएल प्रश्नों को बदलने से तालिका की संरचना को बदल देंगे (आदि, कहते हैं जोड़ने अनुक्रमित) है। एसक्यूएल प्रश्न हाइबरनेट का उपयोग करके स्वतः उत्पन्न होते हैं, इसलिए उन लोगों को अधिक या कम तय करें।

+0

मुझे लगता है कि आपका मतलब मूल्य 1, मूल्य 2 आपके अपडेट में है, हां? – paxdiablo

+0

कोई बात नहीं, यह वैल्यू 1 के मूल्य के बारे में @ Quassnoi के स्पष्टीकरण के कारण वैसे भी काम नहीं करेगा। यह मूल्य 1 के एक मूल्य के लिए काम करता था लेकिन मैंने इस सवाल को पर्याप्त रूप से नहीं पढ़ा। शुभकामनाएँ। – paxdiablo

+0

क्या आप सीधे अपनी क्वेरी में फ़ील्ड का उपयोग करते हैं या आप फ़ंक्शंस का उपयोग कर रहे हैं? एक टाइमस्टैम्प फ़ील्ड और WEEK (टाइमस्टैम्प) की तरह। –

उत्तर

19

आप इस मामले में एक इंडेक्स का उपयोग नहीं कर सकते, क्योंकि आप RANGE फ़िल्टरिंग स्थिति का उपयोग करते हैं।

आप की तरह कुछ का उपयोग करना चाहते हैं:

SELECT * 
FROM values_table this_ 
WHERE this_.value1 = @value 
ORDER BY 
     value2 
LIMIT 10 

, तो (VALUE1, VALUE2) पर एक समग्र सूचकांक बनाने दोनों को छानने के लिए और आदेश देने के लिए इस्तेमाल किया जाएगा।

लेकिन आप एक विस्तृत स्थिति का उपयोग करते हैं, यही कारण है कि आपको वैसे भी ऑर्डर करने की आवश्यकता होगी।

आपका समग्र सूचकांक इस तरह दिखेगा:

 
value1 value2 
----- ------ 
1  10 
1  20 
1  30 
1  40 
1  50 
1  60 
2  10 
2  20 
2  30 
3  10 
3  20 
3  30 
3  40 

, और यदि आप value1 में 1 और 2 का चयन करें, आप अभी भी value2 की एक पूरी क्रमबद्ध सेट नहीं मिलता है।

तो value2 पर अपने सूचकांक बहुत चयनात्मक नहीं है (।। मैं ई वहाँ कई DISTINCT value2 तालिका में नहीं हैं), तो आप की कोशिश कर सकते:

CREATE INDEX ix_table_value2_value1 ON mytable (value2, value1) 

/* Note the order, it's important */  

SELECT * 
FROM (
     SELECT DISTINCT value2 
     FROM mytable 
     ORDER BY 
       value2 
     ) q, 
     mytable m 
WHERE m.value2 >= q.value2 
     AND m.value2 <= q.value2 
     AND m.value1 BETWEEN 13123123 AND 123123123 

यह एक SKIP SCAN अभिगम विधि कहा जाता है। MySQL इसे सीधे समर्थन नहीं करता है, लेकिन इसे इस तरह अनुकरण किया जा सकता है।

RANGE एक्सेस इस मामले में उपयोग किया जाएगा, लेकिन संभवत: आपको DISTINCT value2 पंक्तियों के 1% से कम होने तक कोई प्रदर्शन लाभ नहीं मिलेगा। की

नोट उपयोग:

m.value2 >= q.value2 
AND m.value2 <= q.value2 

बजाय

m.value2 = q.value2 

यह MySQL प्रदर्शन RANGE प्रत्येक पाश की जाँच कर बनाता है।

+0

+1 मुझे याद आया :-) – paxdiablo

+0

आपके व्यापक उत्तर के लिए धन्यवाद। यह मानते हुए कि मैं उपयोग किए गए एसक्यूएल प्रश्नों को बदलने में असमर्थ हूं (वे हाइबरनेट द्वारा स्वतः उत्पन्न होते हैं), क्या आपको विश्वास है कि यह हल करना असंभव है (बेहतर अनुक्रमणण जोड़कर)? – knorv

+0

एक और सवाल: यदि श्रेणी पूछताछ समस्या है, तो ऑर्डर द्वारा उपयोग नहीं करते समय सब ठीक कैसे लगता है? क्षमा करें अगर मैं इस विवरण पर चूक गया। – knorv

0

ऐसा लगता है कि आपके पास दो पूरी तरह से स्वतंत्र कुंजी हैं, एक मान 1 के लिए और एक मान 2 के लिए।

तो जब आप पुनर्प्राप्त करने के लिए value1 कुंजी का उपयोग करते हैं, तो रिकॉर्ड्स आवश्यक रूप से मूल्य 2 के क्रम में वापस नहीं आते हैं, इसलिए उन्हें सॉर्ट करना होगा। यह अभी भी पूर्ण तालिका स्कैन से बेहतर है क्योंकि आप केवल उन रिकॉर्ड्स को सॉर्ट कर रहे हैं जो आपके "कहां मान 1" खंड को संतुष्ट करते हैं।

मुझे लगता है (यदि यह MySQL में संभव है), (value1, value2) पर एक समग्र कुंजी इसे हल करेगी।

प्रयास करें:

CREATE TABLE values_table (
    id int(11) NOT NULL auto_increment, 
    ... 
    value1 int(10) unsigned NOT NULL default '0', 
    value2 int(11) NOT NULL default '0', 
    PRIMARY KEY (id), 
    KEY value1 (value1), 
    KEY value1and2 (value1,value2), 
) ENGINE=MyISAM AUTO_INCREMENT=2364641 DEFAULT CHARSET=utf8; 

(या समकक्ष ALTER TABLE), यह सोचते हैं कि एक समग्र कुंजी के लिए MySQL में सही सिंटैक्स है।

सभी डेटाबेस में मुझे पता है (और मुझे स्वीकार करना है कि MySQL उनमें से एक नहीं है), जिससे डीबी इंजन पंक्तियों को पुनः प्राप्त करने के लिए value1and2 कुंजी का चयन करेगा और उन्हें पहले से ही value2-in- value1 ऑर्डर, इसलिए फ़ाइल प्रकार की आवश्यकता नहीं होगी।

यदि आपको इसकी आवश्यकता है तो भी आप मूल्य 2 कुंजी रख सकते हैं।

+0

हाय, आपके त्वरित उत्तर के लिए धन्यवाद। मैंने आपके सुझाए गए समाधान की कोशिश की है, और दुर्भाग्यवश यह काम नहीं किया। मैंने अपने प्रश्न में एक स्पष्टीकरण जोड़ा है। – knorv

+0

कोई जांच नहीं, @Quassnoi की तरह दिखता है MySQL का अधिक ज्ञान है इसलिए मैं आपको इसे छोड़ दूंगा। रेंज वैल्यू 1 के लिए सॉर्टिंग की आवश्यकता क्यों है, इसकी व्याख्या यह है कि मैंने इस सवाल से कुछ नहीं उठाया - डीबी 2 की समान जांच होगी। सामुदायिक-विकी के रूप में टिप्पणी करते हुए कोई भी एक ही गलती नहीं करता है। – paxdiablo

+0

कुछ प्रकार की एसओ बग है जो मुझे प्रश्न समुदाय-विकी को चिह्नित करने से रोकती है। – paxdiablo

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

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