如果执行下面语句,需要执行几次树的操作,会扫描多少行?
select * from T where k between 3 and 5;
当前表的建表语句如下:
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');
看下当前这条select * from T where k between 3 and 5;的SQL语句执行流程:
- 1.在K索引树上找到k=3的记录,取得ID=300;
- 2.再到ID索引树查找ID=300对应的R3;
- 3.在K索引树取下一个值 k=5,取得ID=500;
- 4.再回到ID索引树查找ID=500对应的R4;
- 5.在K索引树取下一个值k=6,不满足条件,循环结束。
从普通索引树回到主键索引树搜索的过程,称为回表。
覆盖索引
如果执行的语句是:
select ID from T where k between 3 and 5;
此时只需要查询ID的值,而ID的值已经在k索引树上了,因此可以直接提供查询结果,无需回表。
这个查询中,索引k已经覆盖了我们的查询需求,所以称之为覆盖索引。
覆盖索引可以减少数的搜索次数,显著提升查询的性能,所以是一个常用的性能优化手段。
最左前缀原则
B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录。
用(name,age)这个联合索引来分析:
当你的逻辑需求是查到所有名字是“张三”的人时,可以快速定位到 ID4,然后向后遍历得到所有需要的结果。
如果你要查的是所有名字第一个字是“张”的人,你的 SQL 语句的条件是"where name like ‘张 %’"。这时,你也能够用上这个索引,查找到第一个符合条件的记录是 ID3,然后向后遍历,直到不满足条件为止。
索引下推
- 作用:减少回表次数
- 原理:可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
如果现在有一个需求:检索出表中“名字第一个字是张,而且年龄是 10 岁的所有男孩”。那么,SQL 语句是这么写的:
select * from tuser where name like '张 %' and age=10 and ismale=1;
在 MySQL 5.6 之前,只能从 ID3 开始一个个回表。到主键索引上找出数据行,再对比字段值; MySQL 5.6 引入的索引下推优化(index condition pushdown), 可以在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。
两张图的区别是,InnoDB 在 (name,age) 索引内部就判断了 age 是否等于 10,对于不等于 10 的记录,直接判断并跳过。在我们的这个例子中,只需要对 ID4、ID5 这两条记录回表取数据判断,就只需要回表 2 次。