之前在网上看到过很多关于mysql联合索引最左前缀匹配的文章,最近面试时和面试官交流,发现面试官大都理解有误,导致于误人子弟。今天就来整理下。

最左前缀匹配原则

在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,示例:

对列col1、列col2和列col3建一个联合索引

KEY test_col1_col2_col3 on test(col1,col2,col3);

查询的时候

SELECT * FROM test WHERE col1="1" AND clo2="2" AND clo4=|"4"

上面这个查询语句执行时会依照最左前缀匹配原则,检索时会使用索引(col1,col2)进行数据匹配。

网上认为,对于(col1,col2,col3)这种查询,只有

SELECT * FROM test WHERE col1="1" ;SELECT * FROM test WHERE col1="1" AND col2="2";SELECT * FROM test WHERE col1="1" AND col2="2" AND col3="3" ;

这三种形式能用到索引。这就是网上对联合索引的简介。

那事实呢?

上代码

我使用最新的MySQL 8.0.12版本,建表语句如下:

CREATE TABLE `itest` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) DEFAULT NULL COMMENT '姓名', `age` int(11) DEFAULT NULL COMMENT '年龄', `power` int(11) DEFAULT NULL COMMENT '权限', `address` varchar(100) DEFAULT NULL COMMENT '地址', `addtime` datetime DEFAULT NULL, PRIMARY KEY (`id`), KEY `itest_udx` (`age`,`power`,`addtime`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8

这里我们建了itest_udx这个联合索引,添加几条数据试试。

INSERT INTO itest (name,age,power,address,addtime) VALUES ('朱元璋',65,12,'hebei','2019-05-14 08:00:00.000'),('李白',33,3,'吐鲁番','2019-05-14 16:00:00.000'),('tom',14,5,'美国','2019-05-02 16:00:00.000'),('小家伙',12,7,'湖北','2006-11-14 16:00:00.000');

好了,我们来测试下。使用EXPLAIN就能看到SQL是否使用索引了。

explain SELECT * FROM itest where age=11;explain SELECT * FROM itest where age=12 and power=5;

为了方便描述,我们把这三个索引字段称为abc。对于a和ab这种形式,可以看到,都使用了索引,没问题。




mysql索引最左原理 mysql索引最左匹配原则_联合索引

联合索引



如果是只查 b呢,有人说按照最左匹配原则是不会用到索引的,有人说会,我们来看看结果




mysql索引最左原理 mysql索引最左匹配原则_字段_02

b不会用到索引



事实证明了不会用到索引,那只查c这个字段会用到索引么?既然只查b用不上,那么只查c应该也用不上,还是用代码验证吧




mysql索引最左原理 mysql索引最左匹配原则_bc_03

c不会用到索引



果然,单独查c也不会用到索引。

到这里我们总结下,对于abc的联合索引,WHERE条件中单独查a字段会用上索引,单独查b和c字段不会用上索引。

那我们试试ba这种查询,理论上按照最做匹配原则肯定不会用到索引,事实呢?




mysql索引最左原理 mysql索引最左匹配原则_mysql索引最左原理_04

ba会用到索引



让人大跌眼镜,ba居然能用到索引,简直让人不可思议!

那试一下bc,看看结果呢?这里就不贴图了,结论是bc用不到索引。

那其他组合呢,我就不试了,我直接贴结果吧




mysql索引最左原理 mysql索引最左匹配原则_联合索引_05


结果有没有让你震惊呢?

那么abc这种组合呢,按照排列组合原理,abc这种组合也有6种组合。根据网上的说法,只有abc组合能用到索引,事实是这样的吗?

结果同样跟网上的大相径庭,全部都会用到索引。

结论

看图就好了


mysql索引最左原理 mysql索引最左匹配原则_字段_06

联合索引使用情况


是不是跟你预料中的完全不一样?

刚才说了,我使用的MySQL版本是8.x,而且数据量不多。也许不同的版本,甚至数据量多少也会导致索引使用情况不一样,但是,那些信誓旦旦就认定联合索引只有a,ab,abc这三种组合能用到索引的,进来挨打。