表結構和數據
CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idx_a_b_c` (`a`,`b`,`c`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
id | a | b | c |
---|---|---|---|
1 | 1 | 5 | 3 |
2 | 5 | 3 | 3 |
3 | 4 | 5 | 9 |
4 | 2 | 6 | 1 |
5 | 4 | 3 | 2 |
6 | 5 | 5 | 5 |
7 | 1 | 2 | 1 |
8 | 5 | 5 | 8 |
9 | 5 | 3 | 9 |
10 | 5 | 5 | 1 |
11 | 5 | 7 | 7 |
SQL
explain select * from t where a = 5 order by c desc;
-- type:ref
-- key:idx_a_b_c
-- ref:const
-- Extra:Using where; Using index; Using filesort
explain select * from t where a = 5 order by b desc;
-- type:ref
-- key:idx_a_b_c
-- ref:const
-- Extra:Using where; Using index
explain select * from t where a = 5 and c = 5 order by b desc;
-- type:ref
-- key:idx_a_b_c
-- ref:const
-- Extra:Using where; Using index
explain select * from t where a = 5 and b = 5 order by c desc;
-- type:ref
-- key:idx_a_b_c
-- ref:const,const
-- Extra:Using where; Using index
explain select * from t where a = 5 and b >= 5 order by c desc;
-- type:range
-- key:idx_a_b_c
-- ref:NULL
-- Extra:Using where; Using index; Using filesort
索引分析
通過觀察聯合索引的數據結構,很明顯就能發現索引都是有序的,使用索引進行排序就是利用了這個特性。
我們來觀察 a = 5
的這一段索引,很容易就能發現,在 a
確定的情況下,b
是有序的,但c
是無序的。a 和 b
命中索引,a 和 c
不命中索引
在 a,b
都確定的情況下,c
是有序的。a,b,c
命中索引
這就是老生常談的 最佳左前綴原則
也叫 最左前綴匹配原則
因此,要讓排序項使用索引進行排序
第一個條件就是:where條件+排序項符合最佳左前綴原則
第二個條件:不能使用條件查詢
這個也可以通過觀察聯合索引得出結論
a = 5 AND b >= 5
顯然是無法保證 c
是有序的
結論
要讓order by
使用索引排序,需要至少滿足以下條件:
- where條件+排序項符合
最佳左前綴原則
- 不能使用條件查詢