执行计划类型

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
最后修改:2022 年 06 月 23 日
如果觉得我的文章对你有用,请点个赞吧~