由两列或以上列组成的索引成为联合索引,联合索引又叫复合索引。
索引覆盖:联合索引中包含了需要查询的所有数据,不需要进行二次查询,直接返回数据。
最左索引匹配原则:使用联合索引时,遵循从左边开始匹配联合索引中列, 在某些条件下,使用部分列查询,联合索引会生效。
索引方法:Hash索引(仅Memory引擎支持)和B-Tree索引,区别,自行百度。
MySQL的SQL的执行过程:
MySQL的优化器: MySQl使用基于成本的优化器(CBO),它会在多个执行路径中选择一个成本最小的路径来作为执行计划。这里的成本代表了表面SQL的IO、CUP等资源的消耗。
EXPLAIN命令:模拟MySQL优化器运行SQL语句,了解MySQL如何处理你的SQL语句。分析SQL查询语句或是表结构的性能瓶颈,如何使用,自行百度。但这里会用到type列:表示访问类型,如果类型是ALL,则证明全表扫描;possible_keys列:显示可能应用在这张表的索引;keys列:显示实际使用到的索引,如果为NULL,则没有使用索引;ken_len列:表示索引中使用的字节数;ref列:显示索引的哪一列被使用。
MySQL数据库版本:5.7.17
User表结构:
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(50) DEFAULT NULL COMMENT '姓名',
`sex` tinyint(4) DEFAULT NULL COMMENT '性别:0:男,1:女',
`age` tinyint(4) DEFAULT NULL COMMENT '年龄',
`mobile` varchar(20) DEFAULT NULL COMMENT '手机号',
PRIMARY KEY (`id`),
) ENGINE=MEMORY AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
估计大家都知道联合索引遵循最左匹配索引的原则,其实这句话只是说对一半,在某些环境下,确实遵循此原则。但是切勿囫囵吞枣,以偏概全。下面,我就说一下,我对这块的一些见解。
如果让联合索引遵循最左匹配索引的原则,首先保证当前表的联合索引使用的方法不是Hash索引,如果使用Hash索引方法,只能全键查找记录。所以,联合索引遵循最左匹配索引的原则,必须使用B-Tree索引方法。其次,如果联合索引使用B-Tree索引方法后,MySQL会使用优化器,对于你的SQL进行优化,你觉得不可能遵循最左匹配原则的where条件,可能已经优化成可以使用最左匹配原则使用联合索引的执行计划。
通过上面的相关概念,我们可以知道MySQL存储引擎中只有Memory引擎支持Hsah索引方法,所以我们要表修改成Memory引擎。
alter table `user` ENGINE = MEMORY;
ALTER TABLE `user` ADD INDEX `jointIndex` (`name`, `sex`, `age`) USING HASH;
测试一:
EXPLAIN SELECT * FROM `user` WHERE sex=1 AND age=20 AND NAME='小张';
结果:
Explain命令 :keys列显示使用了我们定义jointIndex索引,证明Hash索引全键查询可以使用索引。
测试一:
EXPLAIN SELECT * FROM `user` WHERE NAME='小张';
结果:
Explain命令 :type类显示类型为ALL,代表全表扫描;keys列显示null,没有用到索引。
EXPLAIN SELECT * FROM `user` WHERE NAME='小张' AND sex=1;
结果:
Explain命令 :type类显示类型为ALL,代表全表扫描;keys列显示null,没有用到索引。
测试三:
EXPLAIN SELECT * FROM `user` WHERE sex=1 AND age=20;
结果:
Explain命令 :type类显示类型为ALL,代表全表扫描;keys列显示null,没有用到索引。
结论:
通过以上三个测试,可以证明使用Hash索引方法,不使用全键查询时,不管尊不遵循最左匹配原则都无法使用联合索引。
在测试B-Tree时,我们要把MySQL的存储引擎切换为InnoDB,把索引方法修改成B-Tree索引,操作方法与《1.证明Hash索引方法,只能全键查找记录》中的方法类似,这里就不错过多演示。
上面的相关概念中说到MySQL优化器,在我们执行SQL时,会对SQL进行优化,选择成本最低的执行路径去执行,我们这里就会用到这个知识点,我会通过一个全键查询来简单说明一下。然后我们再演示,最左索引匹配原则生效与失效。
测试语句:
EXPLAIN SELECT * FROM `user` WHERE sex=1 AND age=20 AND NAME='小张';
EXPLAIN SELECT * FROM `user` WHERE age=20 AND sex=1 AND NAME='小张';
EXPLAIN SELECT * FROM `user` WHERE age=20 AND NAME='小张' AND sex=1;
结果:
通过结果我们可以看出,乱序where条件,最后都使用类联合索引,这都是MySQL优化器的功劳
通过2.1,我们知道MySQL都会查询进行优化,在使用最左索引匹配原则的时候,也会优化。接下来我们会通过单where条件、两个where条件进行验证最左索引匹配原则生效与失效。
测试语句:
EXPLAIN SELECT * FROM `user` WHERE NAME='小张'; // 1
EXPLAIN SELECT * FROM `user` WHERE sex=1; // 2
EXPLAIN SELECT * FROM `user` WHERE age=20; // 3
结果:
通过结果发现,只有1使用联合索引。
测试语句:
EXPLAIN SELECT * FROM `user` WHERE NAME='小张' AND sex=1; // 1
EXPLAIN SELECT * FROM `user` WHERE sex=1 AND NAME='小张'; // 2
EXPLAIN SELECT * FROM `user` WHERE NAME='小张' AND age=20; // 3
EXPLAIN SELECT * FROM `user` WHERE sex=1 AND age=20; // 4
结果:
通过1和2,可以看出MySQL优化器对SQL进行优化,两个都使用了最左匹配原则,通过3,我们可以看出它也使用了最左匹配原则,发现他只有一列使用了索引,通过绿框可以看出来。通过4,可以看出它没有使用索引。
结论:
只要where条件,包含联合索引的第一列,都可以使用最左索引原则(前提,SQL语句避免其他原因的索引失效,例如列有null值、where等号前使用函数、Like条件前加%号等)。
上面是我本人一些见解,学艺不精,如有偏差,请君不吝赐教!