MySQL的执行原理之查询成本详解(一)

发布于:2024-07-26 ⋅ 阅读:(278) ⋅ 点赞:(0)

1.什么是成本

MySQL执行一个查询可以有不同的执行方案,它会选择其中成本最低,或者说代价最低的那种方案去真正的执行查询。不过我们之前对成本的描述是非常模糊的,其实在MySQL中一条查询语句的执行成本是由下边这两个方面组成的:

I/O成本

我们的表经常使用的MyISAM、InnoDB存储引擎都是将数据和索引都存储到磁盘上的,当我们想查询表中的记录时,需要先把数据或者索引加载到内存中然后再操作。这个从磁盘到内存这个加载的过程损耗的时间称之为I/O成本。

CPU成本

读取以及检测记录是否满足对应的搜索条件、对结果集进行排序等这些操作损耗的时间称之为CPU成本。

对于InnoDB存储引擎来说,页是磁盘和内存之间交互的基本单位。

MySQL规定读取一个页面花费的成本默认是1.0(I/O成本)

读取以及检测一条记录是否符合搜索条件的成本默认是0.2(CPU成本)

1.0、0.2这些数字称之为成本常数,这两个成本常数我们最常用到,当然还有其他的成本常数。

注意,不管读取记录时需不需要检测是否满足搜索条件,哪怕是空数据,其成本都算是0.2。

2.单表查询的成本

2.1.基于成本的优化步骤实战

在一条单表查询语句真正执行之前,MySQL的查询优化器会找出执行该语句所有可能使用的方案,对比之后找出成本最低的方案,这个成本最低的方案就是所谓的执行计划,之后才会调用存储引擎提供的接口真正的执行查询,这个过程总结一下就是这样:

1、根据搜索条件,找出所有可能使用的索引

2、计算全表扫描的代价

3、计算使用不同索引执行查询的代价

4、对比各种执行方案的代价,找出成本最低的那一个

下边我们就以一个实例来分析一下这些步骤,单表查询语句如下:

SELECT * FROM order_exp WHERE order_no IN ('DD00_6S', 'DD00_9S', 'DD00_10S') 
AND  expire_time> '2021-03-22 18:28:28' AND expire_time<= '2021-03-22 18:35:09' 
AND insert_time> expire_time AND order_note LIKE '%7****排1%' AND  order_status = 0;

看上去有点儿复杂,我们一步一步分析一下。

1. 根据搜索条件,找出所有可能使用的索引

我们前边说过,对于B+树索引来说,只要索引列和常数使用=、<=>、IN、NOT IN、IS NULL、IS NOT NULL、>、<、>=、<=、BETWEEN、!=(不等于也可以写成<>)或者LIKE操作符连接起来,就可以产生一个所谓的范围区间(LIKE匹配字符串前缀也行),MySQL把一个查询中可能使用到的索引称之为possible keys。

我们分析一下上边查询中涉及到的几个搜索条件:

order_no IN ('DD00_6S', 'DD00_9S', 'DD00_10S') ,这个搜索条件可以使用二级索引idx_order_no。

expire_time> '2021-03-22 18:28:28' AND expire_time<= '2021-03-22 18:35:09',这个搜索条件可以使用二级索引idx_expire_time。

insert_time> expire_time,这个搜索条件的索引列由于没有和常数比较,所以并不能使用到索引。

order_note LIKE '%hello%',ord