05深入浅出索引(下)
作者:互联网
什么是回表
初始化建表语句:
mysql> create table T (
ID int primary key,
k int NOT NULL DEFAULT 0,
s varchar(16) NOT NULL DEFAULT '',
index k(k))
engine=InnoDB;
insert into T values(100,1, 'aa'),(200,2,'bb'),(300,3,'cc'),(500,5,'ee'),(600,6,'ff'),(700,7,'gg');
如果执行
select * from T where k between 3 and 5;
需要执行几次树的搜索操作,会扫描多少行?
sql
执行流程:
-
在k索引树上找到k=3的记录,取得 ID = 300。
-
再到ID索引树查到ID=300对应的
R3
。 -
在k索引树取下一个值k=5,取得ID=500。
-
再回到ID索引树查到ID=500对应的
R4
。 -
在k索引树取下一个值k=6,不满足条件,循环结束。
即:虽然读了三条记录出来,但是扫描行数是2。
在整个搜索过程中,由于查询结果所需要的数据只在主键索引上有,所以不得不回表查询,共回表了两次。
问题:能不能优化索引,避免回表查询,提升查询性能呢?
覆盖索引(减少回表查询次数)
如果执行的语句是
select ID from T where k between 3 and 5;
这时只需要查ID的值,而ID的值已经在k索引树上了,因此可以直接提供查询结果,不需要回表。也就是说,在这个查询里面,索引k已经“覆盖了”我们的查询需求,我们称为覆盖索引。
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用的性能优化手段。
覆盖索引扩展
初始化市民表
CREATE TABLE `tuser` (
`id` int(11) NOT NULL,
`id_card` varchar(32) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`ismale` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_card` (`id_card`),
KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB
问题:在一个市民信息表上,是否有必要将身份证号和名字建立联合索引?
我们知道,身份证号是市民的唯一标识。也就是说,如果有根据身份证号查询市民信息的需求,我们只要在身份证号字段上建立索引就够了。而再建立一个(身份证号、姓名)的联合索引,是不是浪费空间?
如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个联合索引就有意义了。它可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。(特殊场景特殊处理)
最左前缀原则(排列字段顺序,缩小索引查询范围)
问题:如果为每一种查询都设计一个索引,索引是不是太多了。如果我现在要按照市民的身份证号去查他的家庭地址呢?又建立一个覆盖索引吗?
解决:
B+树这种索引结构,可以利用索引的“最左前缀”,来定位记录。(定位记录即缩小查询范围)
用(name,age)这个联合索引
由图可以看出,索引项是按照索引定义里面出现的字段顺序排序的。
当你的逻辑需求是查到所有名字是“张三”的人时,可以快速定位到ID4
,然后向后遍历得到所有需要的结果。不用全部扫描,缩小查询的范围。
即,在建立联合索引的时候,安排好索引内的字段顺序可以有效提高查询性能。
索引下推(过滤掉条件不满足的数据,减少回表次数)
在最左前缀索引的基础上,使用索引下推来减少回表次数,提升查询效率。
如:
mysql> select * from tuser where name like '张%' and age=10 and ismale=1;
你已经知道了前缀索引规则,所以这个语句在搜索索引树的时候,只能用 “张”,找到第一个满足条件的记录ID3
。然后呢?
在MySQL 5.6
之前,只能从ID3
开始一个个回表。到主键索引上找出数据行,再对比字段值。
在MySQL 5.6
引入的索引下推优化(index condition pushdown)
, 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
执行流程:
-
先按顺序把“name第一个字是’张’”的记录一条条取出来回表。因此,需要回表4次。
-
对于不等于10的记录,直接判断并跳过。在我们的这个例子中,只需要对
ID4
、ID5
这两条记录回表取数据判断,就只需要回表2次。(过滤掉第一步中不满足条件的数据,减少回表的次数)
总结
在满足语句需求的情况下, 尽量少地访问资源(如减少回表查询)是数据库设计的重要原则之一。
写在最后:本系列参考极客时间mysql实战45讲系列文章,只做学习笔记,原文请前往官网查看。
标签:05,深入浅出,身份证号,查询,回表,索引,NULL,ID 来源: https://www.cnblogs.com/l12138h/p/16377154.html