问题
最近看到一个问题就是一个大表有大约2000万行的数据,其统计数据还是1500万,且收集的时间为去年,其实我们知道一般来讲我们表的数据更改超过10%会重新收集统计数据,统计数据在非dive(eq_range_index_dive_limit参数相关)的情况下就会使用统计数据作为优化器判断执行计划的标准。
何时进行统计数据收集
我们这里只看默认配置下的持久化(PERSISTENT)统计数据的收集方式。实际上在每次更新的时候都会将这个表的modify计数器增加1,然后判断是否需要收集,则收集的逻辑大约如下:
if (dict_stats_is_persistent_enabled(table)) { if (counter > n_rows / 10 /* 10% */ && dict_stats_auto_recalc_is_enabled(table)) { dict_stats_recalc_pool_add(table); table->stat_modified_counter = 0; } return; }
其他条件都比较固定,因为我们是默认的参数设置,那么只有counter 这样一个计数器,其来自于innodb的结构dict_table_t.stat_modified_counter。如果counter 的量超过总量的当前统计数据行数的1/10,则需要收集统计数据,会推给我们的后台收集线程进行统计数据收集。
可能的原因
但是问题是这个counter计数器,会在table share过期后重新加载进来的时候归0,那么
-
flush table(flush table with read loc