InnoDB中dict_update_statistics调用策略及问题-阿里云开发者社区

开发者社区> 数据库> 正文
登录阅读全文

InnoDB中dict_update_statistics调用策略及问题

简介:

背景

         为了提供优化器支持,InnoDB维护了每个表的索引统计信息(index statistics)。在之前的一篇文章中作过介绍。

         文章里面介绍到索引统计信息有几个更新策略,并建议允许关闭动态更新。顺便提及,5.6已经提供了Persistent Statistics 选项,达到相同的目的。

         5.5版本还是必须动态更新。本文介绍在动态更新时的一个问题。

 

索引统计的动态更新策略

         这个策略是比较简单的。每个表维护一个stat_modified_counter每次增、删、改一行时加1,当counter满足一下两个条件之一时,则进行依次动态统计,之后清5.5.29

1)             1) counter > 2000000000

2)             2) counter > 16 + table->stat_n_rows / 16

table->stat_n_rows表的总行数目(估计值)

 

row_update_statistics_if_needed(

/*============================*/

        dict_table_t*   table)  /*!< in: table */

{

        ulint   counter;

 

        counter = table->stat_modified_counter;

        table->stat_modified_counter = counter + 1;

 

        if (counter > 2000000000

            || ((ib_int64_t)counter > 16 + table->stat_n_rows / 16)) {

 

                dict_update_statistics(table, FALSE /* update even if stats

                                                    are initialized */);

        }   

 

执行索引统计的函数是dict_update_statistics,在执行统计期间,对stat加一个x锁。

 

存在问题

由于这个值不要求精确,因此在counter更新时并未加锁。这个问题并不大,但是未加锁导致另外一个问题:短时间内多次调用dict_update_statistics

         stat_modified_counter0是在dict_update_statistics中调用的,但若有多个线程同时判断后进入dict_update_statistics,则会导致多次调用。

         在一个测试场景我们从现场看到同一个时刻用11个用户线程调用dict_update_statistics。这意味着至少多调用了10次索引统计。而索引统计的方法是通过从表中取样本估算的,如果表数据较多,这个索引统计的浪费就很明显了。对查询和更新性能都会有影响。

 

简单修改

         dict_update_statistics的逻辑流程是

1)             1) x

2)             2) 索引统计

3)             3) stat_modified_counter 0

4)             4) 解锁

 

简单修改可以在加x锁之后再次判断stat_modified_counter是否需要进行索引统计,若不需要则解锁返回即可。

5.6已经提供了Persistent Statistics 选项,但若关闭,也会有这个问题。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
数据库
使用钉钉扫一扫加入圈子
+ 订阅

分享数据库前沿,解构实战干货,推动数据库技术变革

其他文章