MySQL物理查询优化技术 —— Index Dive

一 引子

在MySQL的官方手册上有这么一句话:

the optimizer can estimate the row count for each range using dives into the index or index statistics.

这是在说: 优化器为每一个范围段(如“a IN (10, 20, 30)”是等值比较, 括3个范围段实则简化为3个单值,分别是10,20,30)估计每个范围段(用范围段来表示是因为MySQL的“range”扫描方式多数做的是范围扫描,此处单值可视为范围段的特例)中包括的元组数, 而估计方法有2种,一是dive到index中即利用索引完成元组数的估算,简称index dive; 二是使用索引的统计数值,进行估算.

相比这2种方式,在效果上:

1 index dive: 速度慢,但能得到精确的值(MySQL的实现是数索引对应的索引项个数,所以精确)

2 index statistics: 速度快,但得到的值未必精确

 

二 深入

为什么要区分这2种方式呢?

简单地说:

1 查询优化器使用代价估算模型计算每个计划的代价,选择其中代价最小的

2 单表扫描时,需要计算代价;所以单表的索引扫描也需要计算代价

3 单表的计算公式通常是:代价=元组数*IO平均值

4 所以不管是哪种扫描方式,都需要计算元组数

5 当遇到“a IN (10, 20, 30)”这样的表达式的时候,发现a列存在索引,则需要看这个索引可以扫描到的元组数由多少而计算其索引扫描代价,所以就用到了本文提到的“index dive”、“index statistics”这2种方式。

 

三 优化

MySQL据此,提供了一个参数“eq_range_index_dive_limit”,指示MySQL在这种情况下使用哪种方式。用法如下:

This variable indicates the number of equality ranges in an equality comparison condition 
when the optimizer should switch from using index dives to index statistics in estimating 
the number of qualifying rows. It applies to evaluation of expressions that have either of 
these equivalent forms, where the optimizer uses a nonunique index to look up col_name 
values:
    col_name IN(val1, ..., valN)
    col_name = val1 OR ... OR col_name = valN

简单来说就是根据eq_range_index_dive_limit参数设置的阀值来按照不同算法预估影响行数,对于IN或OR条件中的每个范围段视为一个元组,对于元组数低于eq_range_index_dive_limit参数阀值时使用index dive,高于阀值时使用

  • index dive:针对每个元组dive到index中使用索引完成元组数的估算,类似于使用索引进行实际查询得到影响行数
  • index statistics:即根据索引的统计数值进行估算,例如索引统计信息计算出每个等值影响100条数据,那么IN条件中包含5个等值则影响5*100条记录

在MySQL 5.6版本中引入eq_range_index_dive_limit参数,默认值为10,通常业务在使用IN时会超过10个值,因此在MySQL 5.7版本中将默认阀值设为200。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值