概述
所谓的访问方法就是你想查出一堆数据,然后把sql丢给mysql,然后mysql根据你的表情况(索引,数据量,查询成本),给出mysql自己认为最优的执行方式,这就是访问方法。mysql给这些执行方法取了独立名字,分别是:const, ref,ref_or_null,range,index,all,index merge
等值查询(单字段单值)(走单个索引)
1.const方法
select * from user where id=? //id是主键(聚簇索引)
select * from user where stu_id=? //学号是唯一索引(二级索引)
1.如果查询的条件是 主键或者唯一索引情况下,那么访问表的方法是const
2.一般来说都是检索一条记录的方法,用到const
3.如果主键或者唯一索引是多列情况下,那么多列都要相等,这个时候才是const
4.如果主键和唯一索引检索了null,对应多条记录,那么就不是const
2.ref方法
select * from user where name=? //name是学生名字(普通二级索引,可重复)
1.如果查询条件是个普通索引,那么并没有唯一性约束,那么可以查询出多条记录,那么这种就是ref
2.ref查询的性能肯定要比const慢的,因为它不能查询到一条马上就返回,需要扫描到所有值等于这个
需要查询索引的值才可返回。
3.对于这个索引是个联合索引来说,那么只要最左边的索引使用上,就是ref了
3.ref_or_null 方法
select * from user where address=? or address is null //查看某个学生的地址是不是没填写(普通二级索引,可重复)
1.如果查询某个索引的值是一个固定值,或者是null,那么就是ref_or_null
2.ref_or_null方法其实查询了两个值的情况,性能肯定是要慢的
总结:这里都是指的的单字段单值(ref_or_null特殊,不要太在意)的情况下,并且这个字段还是索引的情况下,那 么就是上述三个方法之一
范围查询(单字段多值)(走单个索引)
range方法
select * from user where id=? or id=? //查询两个主键值
select * from user where id>? and id <? //查询两个主键值之间的记录
范围查询,一般指的是走了某个索引字段,并且值是一个区间的情况,那么就是range
索引合并(走多个索引)
1.Intersection合并
select * from user where name=? and address=? name和address都是二级普通索引
1.这种情况下,可能会查询两个索引,最后对两个索引查到的主键进行合并,最后获取到交集的主键进行
回表,返回给客户端,这就是index merge(Intersection合并)
2.mysql会估算成本,如果发现成本比较高,那么还是会选择单纯的单索引,方法就是ref了
3.这里注意要是等值,两个字段,两个索引等值情况下,才会考虑Intersection合并
select * from user where name=? and id>? name是普通二级索引,id是主键
Intersection合并 还是主键的合并,先使用name进行检索,获取到的主键列表先不回表
直接和主键条件做合并,也是会触发Intersection合并
2.Union合并
select * from user where name=? or address=? name和address都是二级普通索引
1.这种情况下,可能会查询两个索引,最后对两个索引查到的主键进行合并,最后获取到并集的主键进行
回表,返回给客户端,这就是index merge(Union合并)
2.mysql会估算成本,如果发现成本比较高,那么还是会选择单纯的单索引,方法就是ref了
3.这里注意要是等值,两个字段,两个索引等值情况下,才会考虑Union合并
select * from user where name=? or id>? name是普通二级索引,id是主键
Union合并 还是主键的合并,先使用name进行检索,获取到的主键列表先不回表
直接和主键条件做并集,也是会触发Union合并
3.Sort-Union合并
select * from user where name>? or address<? name和address都是二级普通索引
1.Sort-Union合并和Union合并的区别很明显,一个是不需要等值,一个需要等值,这其实是因为在进行
主键合并的时候,其实为了降低合并的时间复杂度,内部有个排序的,而等值本身就是有序的两个集合.
2.Sort-Union合并肯定是要性能低于Union合并,毕竟数据量大,内部还需要做个主键排序,才能进行主键
合并,最后使用合并后的主键回表
总结:为什么没有Sort-Intersection? 为什么要等值? 为什么Sort-Union可以不等值? 答案:都是考虑 回表成本和索引合并的原因.详细可以了解具体合并索引细节
其它
1.index方法
select name from user where address=? 假设 name和address是联合索引,我们其实没用到索引,但是 只要查询联合索引上字段
1.一般指的是没有走索引,需要扫描二级索引,但是不要扫描聚簇索引情况,就是index
2.一般发生在联合索引不生效,查询字段又不要回表情况下
2.all方法
select * from user where address=? 假设 name和address是联合索引,我们其实没用到索引,但是 要查询所有字段
一般在分析之后发现无索引可用(数据占比高),查询字段又是全部数据,那么直接走all,
直接扫描聚簇索引