1、简介
SQL查询之前,会先经过「查询优化器」,优化器会基于最低成本选择用什么方式查询,是全表还是某个索引;
成本最低的方案,就是「执行计划」,之后会调用存储引擎接口查询数据;
2、成本分类
I/O成本
InnoDB存储引擎将数据与索引存储在磁盘,我们需要查询表数据时,会从磁盘把数据加载到内存中。从磁盘到内存加载过程所消耗的时间称为I/O成本。
CPU成本
读取以及检测记录是否符合条件、对结果排序等。这些操作的耗时称为CPU成本。
InnoDB规定读取一页成本为1,读取一条以及检测是否符合规则成本为0.2;
3、优化步骤
3.1、根据查询条件,获取可能用到的查询;
主键索引、某些普通索引;
3.2、计算全表扫描的成本
- 全表扫描就是将「聚簇索引」全部数据与查询条件做对比,符合条件的加入结果集;
- 全表扫描成本:I/O成本+CPU成本。所以需要知道,全表有多少页,有多少记录,才可以算出成本;
- 通过
show table status like 表
, 获取到rows、data_length字段;
rows:是有多少条记录;
data_length = 页数量 * 页大小(默认16KB);
页数量 = data_length / 16 / 1024;
总成本 = I/O成本 + CPU成本 = 页数量 * 1 + rows * 0.2;
3.3、计算主键索引扫描成本
计算主键索引成本:主要是知道where条件在主键索引B+树中存在多少条记录;
- I/O成本为1。当从索引中查询数据,不管是 =、in、>、<查询,查询优化器都认为I/O成本跟读取一页的成本相同;
- 计算CPU成本。 =、in、>、<都是有范围的,CPU成本就是范围内的记录数 * 0.2;
3.3、计算二级索引扫描成本
- 二级索引需要回表操作,需要把回表的成本也加上。
回表成本:select * from 表 where id in ( 主键1,主键2,主键3);
总成本 = 二级索引查询成本 + 回表成本;
- 如果in中的个数过多(超过200个),会通过
show index form 表
,查询到索引大概的数据。 - NULL的问题。InnoDB认为每个null都是相等的,如果某个索引中null值特别多的话,会让优化器认为平均一个值重复次数特别多,则不使用索引进行访问。
最好不要允许索引允许为null;