MySQL-覆盖索引总结笔记

什么叫做覆盖索引?
解释一: 就是select的数据列只用从索引中就能够取得,不必从数据表中读取,换句话说查询列要被所使用的索引覆盖。
解释二: 索引是高效找到行的一个方法,当能通过检索索引就可以读取想要的数据,那就不需要再到数据表中读取行了。如果一个索引包含了(或覆盖了)满足查询语句中字段与条件的数据就叫做覆盖索引。
解释三:是非聚集组合索引的一种形式,它包括在查询里的Select、Join和Where子句用到的所有列(即建立索引的字段正好是覆盖查询语句[select子句]与查询条件[Where子句]中所涉及的字段,也即,索引包含了查询正在查找的所有数据)。
不是所有类型的索引都可以成为覆盖索引。覆盖索引必须要存储索引的列,而哈希索引、空间索引和全文索引等都不存储索引列的值,所以MySQL只能使用B-Tree索引做覆盖索引当发起一个被索引覆盖的查询(也叫作索引覆盖查询)时,在EXPLAIN的Extra列可以看到“Using index”的信息。
注:遇到以下情况,执行计划不会选择覆盖查询。
①:select选择的字段中含有不在索引中的字段,即索引没有覆盖全部的列。
②:where条件中不能含有对索引进行like的操作。

是否走索引,查询示例如下:

CREATE TABLE `t_user` (
  `id` bigint(100) NOT NULL AUTO_INCREMENT,
  `password` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `phone` varchar(11) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `nick_name` varchar(255) DEFAULT NULL,
  `sex` int(255) DEFAULT NULL,
  `birthday` datetime DEFAULT NULL,
  `class_id` int(11) DEFAULT NULL COMMENT '班级id',
  PRIMARY KEY (`id`),
  KEY `index_phone` (`phone`) USING BTREE,
  KEY `index_birthday` (`birthday`) USING BTREE,
  KEY `index_name` (`name`,`age`) USING BTREE    # 联合索引
) ENGINE=InnoDB AUTO_INCREMENT=1588138958133 DEFAULT CHARSET=utf8;

 

 

1:如上图所示:这次走的是覆盖索引,因为索引中包含了要查询的列字段,在联合索引中,或者是单个索引,所要查询的列的是索引的子集或者是相等,才能走覆盖索引,否则是要回表的(列id主键除外)。但是需要注意的是靠左匹配查询,这个是很重要的。在实际开发中,尽量使用覆盖索引,减少回表的操作。

select age, name from t_user where age = '32'  --- 走索引 覆盖索引
select age from t_user where age = '32'           ------- 走索引 覆盖索引

select age, sex from t_user where age = '32'   ------- 不走索引 全表扫描
select sex from t_user where age = '32'         ------- 不走索引 全表扫描

select age, name from t_user where name = '32'   ------- 走索引 覆盖索引
select sex from t_user where name = '32'    ------- 走索引 非覆盖索引

select name,age, phone from t_user where name = '32'  ------- 走索引 非覆盖索引
select sex from t_user where name = '32'      ------- 走索引 非覆盖索引

select id from t_user where name = '32' ------- 走索引 覆盖索引
select id from t_user where age = '32' ------- 走索引 覆盖索引

总结:
①:在innodb存储引擎中,分为主键索引和辅助索引。只有在主键索引中,叶子节点存储的是数据记录(一行行的数据),且数据是按照主键从小到大的顺序进行排序。所以建议在排序的时候,排序字段最好也是创建索引,这样减少数据在内存中的排序时间。辅助索引叶子节点存储的是主键。
②:在innodb存储引擎中,表一定要创建主键索引,否则在等值查询中,会锁住全表,而不是锁住的某一行数据(行锁)。
③:在innodb存储引擎中,模糊查询like "XX%"不一定会走索引,因为考虑到列的离散型,列离散型越大,会走索引的可能性会比较大。比如像"aa1","aa2"..."aan",是不会走索引的。
④:在innodb存储引擎中,范围查询之后索引失效。比如index(name,age,phone), where name = 'guodong' and age > 20 and phone = '15317700182',这个时候只匹配name和age,phone是不会走索引的,原因也是列的离散型。
⑤:MySQL数据库服务器执行器优化的,比如index(name,age),where age = 12 and name = 'guodong',这个时候也是会走索引的,但是会有一个性能开销,所以还是最好是完全匹配。

 

posted @ 2020-06-08 11:46  郭慕荣  阅读(912)  评论(0编辑  收藏  举报