一、覆盖索引
执行流程:首先在k索引树上找到k=3的记录,取得id=300,在到id索引等于300上找到对应300的R3,在取下一个k索引为5,同样找到id索引中id=500,在取下一个索引k=6不满足,循环结束
回表:回到主键索引搜索的过程称之为回表
如果查询的字段在k索引上了,那么就不用回表查询了。
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以我们使用覆盖索引是一个常用的优化手段
问题1、在一个市民信息表上,是否有必要将身份证号和名字建立联合索引?
根据业务而定:如果有个查询需求很频繁,是根据身份证号查询查姓名,那么就是有必要的创建联合索引的,因为字符覆盖,可以减少回表操作。
二、最左前缀原则
B+ 树这种索引结构,可以利用索引的“最左前缀”,来定位记录。
问题:在建立联合索引的时候,如何安排索引内部的字段排序?
- 第一原则:如果可以调整顺序,可以少维护一个索引,那么这个顺序是优先考虑的。
- 考虑空间,比如:(name,age),(age)
三、索引下推
还是以市民表的联合索引(name, age)为例。如果现在有一个需求:检索出表中“名字第一个字是张,而且年龄是 10 岁的所有男孩”。那么,SQL 语句是这么写的:
mysql> select * from tuser where name like '张%' and age=10 and ismale=1;
根据最左匹配原则,找到张的 找到第一个满足条件的记录ID3。
注意这块和版本有区别:
mysql5.6之前只能从ID3开始一个一个回表,到主索引中找出数据行,在对比字段值。
Mysql5.6引入索引下推,在索引遍历的过程中,对索引包含的字段,先做判断,直接过滤掉不满足的条件记录,减少回表次数。
无索引下推:
有索引下推:
四、explain详解
1、explain的两个变种
explain extend :会在额外的基础上提供一些查询优化,后紧跟show warning 可以得到优化后的查询语句。
explain partition: 相比于explain多了个partition字段,如果查询是基于分区表的话,会显示查询访问的分区。
id列:
select_type列:是简单查询还是复杂查询(simple,primary,subquery,derived)
**table列:**explain正在访问那个表,当from字句查询时,<derivenN >
当有union时,table列的值,`<union1,2>,1,2代表是参与union的select 行id
type列:`
2、explain中的列
解决like’%字符串%'索引不被使用的方法?
答:使用覆盖索引,查询的字段必须建立索引字段。
如果不能使用覆盖索引,则可能借助搜索引擎。
1、索引的最佳实践
1、全值匹配
2、最左前缀法则
3、不在索引上做任何操作(计算&函数& 自动or手动 类型转化)
4、存储引擎不能使用索引中范围条件右边的列
5、尽量使用覆盖索引,减少使用select *
6、mysql 使用!= 或者 <> ,not in ,not exists,无法使用索引,导致扫描全表
7、is null ,is not null 一般情况下,无法使用索引
8、like % 开头 索引会失效
9、字符串不加单引号,索引失效,因为需要转化
10、少用or 或者in ,用它查询时候,mysql不一定使用索引,mysql内部优化器会根据检索比例,表大小,多个因素评定是否使用索引。
11、范围查询优化:可以将大的范围拆成多个小的范围
索引使用总结:
五、小结
- 覆盖索引
- 前缀索引
- 索引下推
重建索引 k 的做法是合理的,可以达到省空间的目的。但是,重建主键的过程不合理。不论是删除主键还是创建主键,都会将整个表重建。所以连着执行这两个语句的话,第一个语句就白做了。这两个语句,你可以用这个语句代替 : alter table T engine=InnoDB。