联合索引最左匹配原则
建表语句:
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(30) DEFAULT NULL COMMENT '名称', `sex` varchar(1) DEFAULT NULL COMMENT '性别', `age` int(11) DEFAULT NULL COMMENT '年龄', `card_no` varchar(30) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_name_sex_card_no` (`name`,`sex`,`card_no`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8;
设置联合索引:
顺序为(`name`,`sex`,`card_no`)分别用a,b,c代表。
-- name, sex, card_no EXPLAIN select * from user where name = '1'; -- a ref EXPLAIN select * from user where name = '1' and sex = '1'; -- ab ref EXPLAIN select * from user where name = '1' and sex = '1' and card_no = '1'; -- abc ref EXPLAIN select * from user where card_no = '1' and sex = '1' and name = '1'; -- cba ref EXPLAIN select * from user where name = '1' and card_no = '1'; -- ac ref EXPLAIN select * from user where card_no = '1' and name = '1'; -- ca ref EXPLAIN select * from user where sex = '1' and card_no = '1'; -- bc ALL EXPLAIN select * from user where sex = '1'; -- b ALL EXPLAIN select * from user where card_no = '1'; -- c ALL -- 最左匹配原则 -- a必须得有 -- 覆盖索引 EXPLAIN select name,sex,card_no from user where name = '1' and sex = '1' and card_no = '1';
依次执行结果:
a
ab
abc
cba
ac
ca
bc
b
c
覆盖索引:即查询的列被索引覆盖。例如abc,查询的字段是abc的列即覆盖索引。
结论:
以a,b,c顺序建立联合索引:
a 使用a索引。type=ref,key_len=93。
ab使用ab索引。type=ref,key_len=99。
abc使用abc联合索引。type=ref,key_len=192。
ac使用a索引。type=ref,key_len=93。
b,c,bc未走索引。type=ALL。
覆盖索引。type=ref。
以上abc的顺序在sql中可随意,mysql执行时会优化顺序,例如cba会优化为abc。
要想使得索引生效索引a必须存在。即最左匹配。
索引原理请参考二叉树,B树,B+树。是一个演变的过程。
参考:
https://blog.csdn.net/weixin_47162914/article/details/123793589?spm=1001.2014.3001.5506