`
丁林.tb
  • 浏览: 789841 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

InnoDB中dict_update_statistics调用策略及问题

阅读更多

背景

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

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

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

 

索引统计的动态更新策略

         这个策略是比较简单的。每个表维护一个stat_modified_counter每次增、删、改一行时加1,当counter满足一下两个条件之一时,则进行依次动态统计,之后清0 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 选项,但若关闭,也会有这个问题。

 

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics