标签:prim 缺省 不同的 *** extra force mysql 设置 ref
MySQL5.6引入了一个新的系统变量eq_range_index_dive_limit。有一个表“t”。主键由从“id1”开始的多个列组成。表t中有1.67M行,id1的基数是46K(这些数字可以通过SHOW TABLE STATUS / SHOW INDEX收集)。因此,每个id1平均有36行(1.67M / 46K = 36),但实际的id1分布是不均匀的。有接近1M行,其中id1在1和10之间。
mysql> explain select count(*)from t force index(PRIMARY)where id1 in(1,2,3,4,5,6,7,8,9)\G
***************** 1.行********** *
id:1
select_type:SIMPLE
table:t
type:range
possible_keys:PRIMARY
key:PRIMARY
key_len:8
ref:NULL
rows:912388
extra:using where;using index
1 row(0.00 sec)
MySQL估计912K行匹配,其中id1 IN(1..9)。这接近实际数字。 MySQL5.6引入了持久化优化器统计,使统计信息更准确。
mysql>explain select count(*)from t force index(PRIMARY)where id1 in(1,2,3,4,5,6,7,8,9,10)\G
***************** 1.行********** *
id:1
select_type:SIMPLE
table:t
type:range
possible_keys:PRIMARY
key:PRIMARY
key_len:8
ref:NULL
rows:360
extra:using where;using index
1 row(0.00 sec)
当添加一个IN条件(id1 IN(1..10))时,突然估计的行数下降到360!这比实际匹配的行数小得多。估计的行数越来越少(或更大)经常使MySQL选择不正确的查询执行计划,所以这是真的很严重。
估计的行数变化很大的原因是一个新的系统变量eq_range_index_dive_limit。如在线手册所述,“如果eq_range_index_dive_limit大于0,如果有eq_range_index_dive_limit或更多相等范围”,优化器将使用现有索引统计信息而不是索引潜水。默认eq_range_index_dive_limit为10.因此,当设置10个或更多IN条件时,MySQL会跳过索引dive,并从统计信息中估计行数。在这个例子中,MySQL估计360行(1.67M(表t的估计总行数)/ 46K(基数id1)* 10(IN条件)== 360)。
通过增加eq_range_index_dive_limit足够大,MySQL不会错误地估计行。
mysql> set session eq_range_index_dive_limit = 1000;
query OK,0 row affected(0.00秒)
mysql>explain select count(*)from t force index(PRIMARY)where id1 in(1,2,3,4,5,6,7,8,9,10)\G
***************** 1.行********** *
id:1
select_type:SIMPLE
table:t
type:range
possible_keys:PRIMARY
key:PRIMARY
key_len:8
ref:NULL
rows:937684
extra:using where;using index
1 row(0.00 sec)
由于SQL强制走了主键索引,在这个例子中MySQL并没有选错执行计划,但eq_range_index_dive_limit对于MySQL选择执行计划的影响显而易见。
在eq_range_index_dive_limit设置过小且索引分布极不均匀的情况下,MySQL可能会由于成本计算误差太大,导致选择错误的执行计划这一灾难性后果!
如果是业务特征决定了需要执行多次类似于上述案例中的SQL,DBA应考虑关闭该特性:
set global eq_range_index_dive_limit = 0;
总结:
eq_range_index_dive_limit有助于减少查询执行计划的index dive成本,但5.6版本缺省值为10,有点偏小,DBA应根据业务特点选择合理的值或者关闭该特性。
注:该参数在MySQL 5.7中缺省值为200。
标签:prim 缺省 不同的 *** extra force mysql 设置 ref
原文地址:http://blog.51cto.com/13476134/2343099