सबसे पहले, आइए FORCE INDEX
को आजमाते हैं ef
. में से किसी एक को चुनने के लिए या fe
. एक स्पष्ट तस्वीर प्राप्त करने के लिए समय बहुत कम है, जो कि तेज़ है, लेकिन `व्याख्या एक अंतर दिखाता है:
filetime
. पर सीमा को बाध्य करना प्रथम। (नोट:WHERE
में ऑर्डर करें कोई प्रभाव नहीं पड़ता।)
mysql> EXPLAIN SELECT COUNT(*), AVG(fsize)
FROM files FORCE INDEX(fe)
WHERE ext = 'gif' AND filetime >= '2015-01-01'
AND filetime < '2015-01-01' + INTERVAL 1 MONTH;
+----+-------------+-------+-------+---------------+------+---------+------+-------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+-------+-----------------------+
| 1 | SIMPLE | files | range | fe | fe | 14 | NULL | 16684 | Using index condition |
+----+-------------+-------+-------+---------------+------+---------+------+-------+-----------------------+
लो-कार्डिनैलिटी ext
को ज़बरदस्ती करना पहला:
mysql> EXPLAIN SELECT COUNT(*), AVG(fsize)
FROM files FORCE INDEX(ef)
WHERE ext = 'gif' AND filetime >= '2015-01-01'
AND filetime < '2015-01-01' + INTERVAL 1 MONTH;
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
| 1 | SIMPLE | files | range | ef | ef | 14 | NULL | 538 | Using index condition |
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
स्पष्ट रूप से, rows
कहते हैं ef
बेहतर है। लेकिन आइए ऑप्टिमाइज़र ट्रेस से जाँच करें। उत्पादन बल्कि भारी है; मैं केवल दिलचस्प भाग दिखाऊंगा। नहीं FORCE
ज़रूरी है; ट्रेस दोनों विकल्प दिखाएगा फिर बेहतर चुनें।
...
"potential_range_indices": [
...
{
"index": "fe",
"usable": true,
"key_parts": [
"filetime",
"ext",
"did",
"filename"
]
},
{
"index": "ef",
"usable": true,
"key_parts": [
"ext",
"filetime",
"did",
"filename"
]
}
],
...
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "fe",
"ranges": [
"2015-01-01 00:00:00 <= filetime < 2015-02-01 00:00:00"
],
"index_dives_for_eq_ranges": true,
"rowid_ordered": false,
"using_mrr": false,
"index_only": false,
"rows": 16684,
"cost": 20022, <-- Here's the critical number
"chosen": true
},
{
"index": "ef",
"ranges": [
"gif <= ext <= gif AND 2015-01-01 00:00:00 <= filetime < 2015-02-01 00:00:00"
],
"index_dives_for_eq_ranges": true,
"rowid_ordered": false,
"using_mrr": false,
"index_only": false,
"rows": 538,
"cost": 646.61, <-- Here's the critical number
"chosen": true
}
],
...
"attached_conditions_computation": [
{
"access_type_changed": {
"table": "`files`",
"index": "ef",
"old_type": "ref",
"new_type": "range",
"cause": "uses_more_keyparts" <-- Also interesting
}
}
fe
. के साथ (श्रेणी स्तंभ पहले), श्रेणी का उपयोग किया जा सकता है, लेकिन यह ext='gif'
के लिए मछली पकड़ने वाली 16684 पंक्तियों के माध्यम से स्कैनिंग का अनुमान लगाता है ।
ef
. के साथ (कम कार्डिनैलिटी ext
पहले), यह सूचकांक के दोनों स्तंभों का उपयोग कर सकता है और बीट्री में अधिक कुशलता से ड्रिल कर सकता है। फिर उसे अनुमानित 538 पंक्तियाँ मिलीं, जो सभी क्वेरी के लिए उपयोगी हैं -- और फ़िल्टरिंग की आवश्यकता नहीं है।
निष्कर्ष:
INDEX(filetime, ext)
केवल पहले कॉलम का इस्तेमाल किया।INDEX(ext, filetime)
दोनों स्तंभों का इस्तेमाल किया।=
में शामिल कॉलम डालें परीक्षण पहले इंडेक्स में कार्डिनैलिटी की परवाह किए बिना ।- क्वेरी योजना पहले 'श्रेणी' कॉलम से आगे नहीं जाएगी।
- "कार्डिनैलिटी" अप्रासंगिक है समग्र अनुक्रमणिका और इस प्रकार की क्वेरी के लिए ।
("इंडेक्स कंडीशन का उपयोग करना" का अर्थ है कि स्टोरेज इंजन (InnoDB) फ़िल्टरिंग के लिए उपयोग किए जाने वाले इंडेक्स से परे इंडेक्स के कॉलम का उपयोग करेगा।)