执行计划类型
const
直接通过聚簇索引或者二级索引+聚簇索引回源,查询到想要的数据。这种根据索引可以直接快速查询到数据的过程,在执行计划里称之为const。
二级索引必须是unique,才是const。否则就是ref
ref
一般走索引都是ref,如果是组合索引,则要求查询条件必须是从索引最左侧开始连续多列都是等值比较。
range
对索引列使用范围查询。
index
只需要遍历二级索引就可以拿到想要的数据,而不需要回源到聚簇索引的访问方式。
索引:
idx(S21,S22,S23,S24)
SQL:
SELECT S21,S22,S23 FROM TABLE WHERE S22 = 'X' AND S23 = 'Z';
第一反应:这个SQL无法直接从联合索引树的根节点进行二分查找。
基于上面的索引以及SQL,可以直接遍历联合索引树的叶子节点,找到所需要的数据,不需要再回源到聚簇索引进行二次查询,这种方式就是使用的index访问。
虽然遍历了叶子节点,但是叶子节点内容少。也比回表查询快。
什么情况下一次查询用到多个索引
现有索引:
idx(x1),idx(x2);
现有SQL:
SELECT * FROM TABLE WHERE X1 = XX AND X2 = ZZ;
在一般情况下,查询优化器生成执行计划只会按照其中一个字段的索引树去查找,然后再回表到聚簇索引查完整数据,然后根据另一个字段的值过滤。
当按照某个索引值查询之后得到了上万条的数据,此时就要考虑再通过另一个索引查询,将两个索引得到的结果的主键进行求交集,然后再去回表查询。
多表关联的SQL语句的执行计划
驱动表与被驱动表
在多表关联查询时,一般是通过部分条件先从一张表中取出符合条件的数据,然后再在这些数据中进行后续的条件匹配。先查询的表叫做驱动表,后查询的表就叫被驱动表。
内连接与外连接
- 内连接:INNER JOIN,连接条件写在WHERE中,并且按照表与表之间的字段关系严格判断,为空的不会显示
- 外连接:[LEFT | RIGHT] OUTER JOIN,连接条件写在ON中;如果是LEFT则表示左侧表中的数据不管右侧表里是否有关联都会返回出来,右侧大不了显示为NULL。
嵌套循环关联
多表关联查询,往往都是利用驱动表的结果,去被驱动表中通过where条件,on条件进行遍历匹配。因此如果关联表很多,就会因为遍历的效率影响整个SQL的执行效率,所以要合理的在驱动表和被驱动表上建立合适的索引。
执行成本的计算
成本的组成
- IO成本
- CPU成本
计算方式
1. MYSQL规定读取一页花费的成本默认是1.0,读取以及检测一条记录是否符合搜索条件的成本默认是0.2。
2. 不管读取到的记录需不需要检测是否符合搜索条件,其成本都是0.2
3. 通过show table status like '表名',可以查看指定表的一些信息
4. rows是表中的记录数(对于innodb来说这个是个估计值),data_length是聚簇索引的字节数大小。通过data_length/(1024*16)可以算出有多少页,就能算出全表扫描的成本。
5. IO成本=数据页数量*1+1.1
6. CPU成本=行记录数*0.2+1.0
7. 总成本=IO成本+CPU成本
计算示例
数据页数=(98304/1024)/16=6
行记录数=603
总成本=6*1+0.2*603=126.6
二级索引要注意的点
- 二级索引在计算时要先计算二级索引根据条件查一波数据的IO成本,比如score between 25,200 or score between 250,300,这是2个范围,否则score=XX就是一个区间。
- 一般一个区间可以简单的认为是一个数据页,也可能是n个数据页,反正是个位数级别的。
- 二级索引得到的结果再回表,一条数据回表一次。
- a104