InnoDB 查询成本
1. 单表查询成本
连接查询总成本 = IO 成本 + CPU 成本
对于 InnoDB
存储引擎来说,页是磁盘和内存之间交互的基本单位,设计MySQL
的大叔规定读取一个页面花费的成本默认是 1.0
,读取以及检测一条记录是否符合搜索条件的成本默认是 0.2
。1.0
、0.2
这些数字称之为 成本常数
,这两个成本常数我们最常用到。
如果是走索引,则需要计算需要回表的记录数量,来计算 CPU 成本。记录数量的计算方式为:先获取索引对应的 B+
树的 区间最左记录
和 区间最右记录
,然后再计算这两条记录之间有多少记录(记录条数少的时候可以做到精确计算,多的时候只能估算)。这种通过直接访问索引对应的 B+
树来计算某个范围区间对应的索引记录条数的方式称之为 index dive
。
与之对应的是「基于索引统计数据」来预估记录条数,一般是发生在使用 IN 进行范围查询,且 IN 里面的条件较多时。因为针对 IN 中的每个单点区间,都需要单独走一次 index dive,一旦数量较多(取决于设置的系统变量 eq_range_index_dive_limit
),那在 index dive 上损耗的性能就会较多。这个时候 MySQL 就会更倾向于用「基于索引统计数据」的方式来预估记录条数。这就解释了为什么使用 IN 时可能会导致索引失效。
2.联表查询成本
连接查询总成本 = 单次访问驱动表的成本 + 驱动表扇出数 x 单次访问被驱动表的成本
这里的扇出数实际上就是驱动表经过条件过滤后剩余的记录数。
3.成本常数
通过调整 server_cost
或者 engine_cost
表的成本常数,可以引导 MySQL 去生成倾向于全表扫描或倾向于搜索索引的执行计划。
参考:《MySQL 是怎样运行的》