mysql单表访问方法

525 阅读4分钟

概述

所谓的访问方法就是你想查出一堆数据,然后把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,
直接扫描聚簇索引