视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
MySQL5.6为什么关闭元数据统计信息自动更新&统计信息收集源代码探索
2020-11-09 12:54:21 责编:小采
文档

问题描述:MySQL5.5.15原sql如下:selectconstraint_schema,table_name,constraint_name,constraint_typefrominformation_schema.table_constraintswheretable_s

./storage/innobase/row/row0mysql.c

/*********************************************************************//** Updates the table modification counter and calculates new estimates for table and index statistics if necessary. */ UNIV_INLINE void row_update_statistics_if_needed( /*============================*/ dict_table_t* table) /*!< in: table */ { ulint counter; counter = table->stat_modified_counter; table->stat_modified_counter = counter + 1; /* Calculate new statistics if 1 / 16 of table has been modified since the last time a statistics batch was run, or if stat_modified_counter > 2 000 000 000 (to avoid wrap-around). We calculate statistics at most every 16th round, since we may have a counter table which is very small and updated very often. */ if (counter > 2000000000 || ((ib_int_t)counter > 16 + table->stat_n_rows / 16)) { dict_update_statistics(table, FALSE /* update even if stats are initialized */); } }

---------------------------------------------------------------------------

#通过更新统计信息stat_modified_counter,每个表都有这个表里来维护:

./storage/innobase/row/row0mysql.c

/*********************************************************************//** Updates the table modification counter and calculates new estimates for table and index statistics if necessary. */ UNIV_INLINE void 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 (DICT_TABLE_CHANGED_TOO_MUCH(table)) { dict_update_statistics( table, FALSE, /* update even if stats are initialized */ TRUE /* only update if stats changed too much */); } } /*********************************************************************/

规则:每一次DML操作导致1 行更新,stat_modified_counter加1,直到满足更新统计信息的条件,stat_modified_counter的值自动重置为0。


#更新统计信息的条件:(有超过1/16的row被更改过会更新表的条件信息)

./storage/innobase/include/dict0dict.h

/** Calculate new statistics if 1 / 16 of table has been modified since the last time a statistics batch was run. We calculate statistics at most every 16th round, since we may have a counter table which is very small and updated very often. @param t table @return true if the table has changed too much and stats need to be recalculated */ #define DICT_TABLE_CHANGED_TOO_MUCH(t) \ ((ib_int_t) (t)->stat_modified_counter > 16 + (t)->stat_n_rows / 16) /*********************************************************************/


* 这样有个性能问题,若有多个线程同时检测到阈值,也即是并发调用会多次,,会导致dict_update_statistics函数多次的调用,浪费了系统资源。

解决方法:在dict_update_statistics{}函数对stat_modified_counter加锁,避免并发执行。


#统计新跟更新函数:dict_update_statistics

下载本文
显示全文
专题