MySQL
版本: SELECT VERSION();
// 8.0.23
组合索引相关的文档:https://dev.mysql.com/doc/refman/8.0/en/multiple-column-indexes.html
EXPLAIN输出相关文档:https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
SQL的执行顺序:https://www.eversql.com/sql-order-of-operations-sql-query-order-of-execution/
DDL
CREATE TABLE `dev` (
`id` int NOT NULL AUTO_INCREMENT,
`x` int NOT NULL DEFAULT '0',
`y` int NOT NULL DEFAULT '0',
`z` int NOT NULL DEFAULT '0',
`m` int NOT NULL DEFAULT '0',
`n` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `idx_x_y_z` (`x`,`y`,`z`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
WHERE 篇
-
EXPLAIN SELECT * FROM dev WHERE x = 1;
// type=ref,因此是一种索引访问。
1.png
-
EXPLAIN SELECT * FROM dev WHERE y = 1;
// type=ALL,因此是全表扫描。
2.png
-
EXPLAIN SELECT x, y, z FROM dev WHERE x = 1 AND y = 2;
// type=ref;Extra=Using index。其中Using index表明MySQL使用覆盖索引。
3.png
-
EXPLAIN SELECT * FROM dev WHERE x > 1 AND y = 2 AND z = 3;
// type=range,即范围扫描,也就是有限制的索引扫描。key_len=4表明仅仅用到了x这个索引。(int占4个字节)
4.png
简单讲就是最左前缀匹配原则,并且要利用组合索引后面的索引,其前面的索引必须是等值查询(其她各种情况可以试试.......
ORDER BY 篇
结合 where 篇的经验,先看看组合索引基于最左前缀匹配原则的等值查询,即x=constant
-
EXPLAIN SELECT * FROM dev WHERE x = 1 ORDER BY y;
// Extra=NULL 预期的结果,索引本来就有序,所有order by
不用单独排序。
5.png
-
EXPLAIN SELECT * FROM dev WHERE x = 1 ORDER BY y ASC, z DESC;
// Extra=Using filesort 其实也很好理解,组合索引(x,y,z)
本来就是有序的,但是在ORDER BY
里,y
和z
的顺序是相反的,那必然得进行额外的排序。
6.png
非等值查询
-
EXPLAIN SELECT * FROM dev WHERE x = 1 and y > 2 ORDER BY z;
// Extra包含Using filesort,因为组合索引(x,y,z)
里,虽然x
,y
都用到了索引,但是y
是范围扫描,因此ORDER BY z
需要额外的排序。如果ORDEY BY z
改为ORDER BY y
则会利用索引,不会有额外的排序。
7.png
网友评论