Đầu tiên, hãy thử FORCE INDEX
để chọn ef
hoặc fe
. Thời gian quá ngắn để có được bức tranh rõ ràng về thời gian nhanh hơn, nhưng `EXPLAIN cho thấy sự khác biệt:
Bắt buộc phạm vi trên filetime
Đầu tiên. (Lưu ý:Thứ tự ở WHERE
không có tác động.)
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 |
+----+-------------+-------+-------+---------------+------+---------+------+-------+-----------------------+
Buộc số lượng thẻ số thấp ext
đầu tiên:
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 |
+----+-------------+-------+-------+---------------+------+---------+------+------+-----------------------+
Rõ ràng, các hàng rows
nói ef
tốt hơn. Nhưng hãy kiểm tra bằng dấu vết của Trình tối ưu hóa. Đầu ra khá cồng kềnh; Tôi sẽ chỉ hiển thị những phần thú vị. Không có FORCE
là cần thiết; dấu vết sẽ hiển thị cả hai tùy chọn sau đó chọn tùy chọn tốt hơn.
...
"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
}
}
Với fe
(cột phạm vi đầu tiên), phạm vi có thể được sử dụng, nhưng nó ước tính quét qua 16684 hàng đánh bắt cá cho ext='gif'
.
Với ef
(số lượng thẻ số thấp ext
đầu tiên), nó có thể sử dụng cả hai cột của chỉ mục và xem chi tiết hiệu quả hơn trong BTree. Sau đó, nó tìm thấy ước tính khoảng 538 hàng, tất cả đều hữu ích cho truy vấn - không cần lọc thêm.
Kết luận:
-
INDEX(filetime, ext)
chỉ sử dụng cột đầu tiên. -
INDEX(ext, filetime)
đã sử dụng cả hai cột. - Đặt các cột liên quan đến
=
bài kiểm tra đầu tiên trong chỉ mục không phân biệt số lượng . - Kế hoạch truy vấn sẽ không vượt ra ngoài cột 'phạm vi' đầu tiên.
- "Cardinality" không liên quan đối với các chỉ mục tổng hợp và loại truy vấn này .
("Sử dụng điều kiện chỉ mục" có nghĩa là Công cụ lưu trữ (InnoDB) sẽ sử dụng các cột của chỉ mục ngoài cột được sử dụng để lọc.)