首頁 資料庫 mysql教程 MySQL5.6为什么关闭元数据统计信息自动更新&统计信息收集源代码

MySQL5.6为什么关闭元数据统计信息自动更新&统计信息收集源代码

Jun 07, 2016 pm 02:55 PM
為什麼 資訊 關閉 數據統計 更新 自動

问题描述: MySQL 5.5.15 原sql如下: select constraint_schema,table_name,constraint_name,constraint_type from information_schema.table_constraints where table_schema not in ('information_schema', 'mysql', 'test',‘performance_schema’); 不

问题描述:

MySQL 5.5.15 原sql如下:

select constraint_schema,table_name,constraint_name,constraint_type from information_schema.table_constraints where table_schema not in ('information_schema', 'mysql', 'test',‘performance_schema’);  

 不只是上面提到的table_constraintsinformation_schema库下的一下几个表,访问时候都会触发这个“顺手”操作。

information_schema.TABLES

information_schema.STATISTICS

information_schema.PARTITIONS

information_schema.KEY_COLUMN_USAGE

information_schema.TABLE_CONSTRAINTS

information_schema.REFERENTIAL_CONSTRAINTS

show table status  . .

show index from ...

innodb_stats_on_metadata=on 都会触发自动更新统计信息。

问题:

5.6 开始默认innodb_stats_on_metadata=off,why??? 答:为了防止自动更新统计信息在DB高峰时导致BP的swap;查询性能大幅度抖动。

没有定期更新统计信息了么??答:有啊,而且可以是持久化的。


我看到的MySQL 5.5.15 这个版本还是条件是====>

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

下面做了对MySQL 收集统计信息做了扩展:


一.下面针对MySQL community(5.5.15、5.5.36、5.6.16)源代码分析:

1.下面是对MySQL-5.5.15 的源代码的分析:

./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_int64_t)counter > 16 + table->stat_n_rows / 16)) {

		dict_update_statistics(table, FALSE /* update even if stats
						    are initialized */);
	}
}
登入後複製

从上面可以看出更新统计信息的条件是:

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


2.下面是对MySQL-5.5.36 的源代码的分析:

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

#通过更新统计信息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_int64_t) (t)->stat_modified_counter > 16 + (t)->stat_n_rows / 16)

/*********************************************************************/
登入後複製


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

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


#统计新跟更新函数:dict_update_statistics

./storage/innobase/dict/dict0dict.c

/*********************************************************************//**
Calculates new estimates for table and index statistics. The statistics
are used in query optimization. */
UNIV_INTERN
void
dict_update_statistics(
/*===================*/
        dict_table_t*   table,          /*!< in/out: table */
        ibool           only_calc_if_missing_stats,/*!< in: only
                                        update/recalc the stats if they have
                                        not been initialized yet, otherwise
                                        do nothing */
        ibool           only_calc_if_changed_too_much)/*!< in: only
                                        update/recalc the stats if the table
                                        has been changed too much since the
                                        last stats update/recalc */
{
        dict_index_t*   index;
        ulint           sum_of_index_sizes      = 0;

        DBUG_EXECUTE_IF("skip_innodb_statistics", return;);
-----------------------------------------------------------------------------
登入後複製

可以优化成:

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

1) x

2) 索引统计

3) stat_modified_counter 0

4) 解锁

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

3.下面我们来看下对MySQL 5.6.16 的源代码的分析:

MySQL版本:MySQL 5.6.16-log。

./storage/innobase/row/row0mysql.cc

void
row_update_statistics_if_needed(
/*============================*/
        dict_table_t*   table)  /*!< in: table */
{
        ib_uint64_t     counter;
        ib_uint64_t     n_rows;

        if (!table->stat_initialized) {
                DBUG_EXECUTE_IF(
                        "test_upd_stats_if_needed_not_inited",
                        fprintf(stderr, "test_upd_stats_if_needed_not_inited "
                                "was executed\n");
                );
                return;
        }

        counter = table->stat_modified_counter++;
        n_rows = dict_table_get_n_rows(table);

        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;
        }

        /* 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. */

        if (counter > 16 + n_rows / 16 /* 6.25% */) {

                ut_ad(!mutex_own(&dict_sys->mutex));
                /* this will reset table->stat_modified_counter to 0 */
                dict_stats_update(table, DICT_STATS_RECALC_TRANSIENT);
        }
}

/*********************************************************************/
登入後複製

从上面的代码看可以看出:

1.对InnoDB表统计信息持久化时,表的row发生变化大于10%(counter > n_rows / 10 /* 10%)并且<span style="color:rgb(79,129,189);">innodb_stats_auto_recalc</span><span style="color:rgb(79,129,189);">=on,统计信信息会更新(虽然</span><span style="color:rgb(79,129,189);">innodb_stats_auto_recalc</span><span style="color:rgb(79,129,189);"><span style="color:rgb(2,103,137);font-family:'Courier New', Courier, fixed, monospace;font-size:13.63636302948px;font-weight:bold;line-height:25.2000007629395px;background-color:rgb(255,255,255);">=on是自动重新计算,但是也是异步的,可能会延时,比如当瞬间的DML批量操作就可能有延时</span>)</span>

2.统计信息非持久化还是和5.5 一致的(表的row发生变化大于1/16时更新统计信息

3.切记:不能完全依赖于MySQL本身的机制来更新统计信息,线上一些表不及时更新统计信息的我遇到过多次,针对这样的表,我在夜间定期analyze table xxx;


二.MySQL 5.6的改进:

可以配置统计信息的持久化和非持久化(非持久化:5.6之前都是这种)

相关参数:

持久化:

innodb_stats_persistent:on(1)

innodb_stats_persistent_sample_pages:20

非持久化:

innodb_stats_sample_pages:8

相关表:

mysql.innodb_index_stats

mysql.innodb_table_stats

From 5.6.6 开始,统计信息默认是持久化的(即innodb_stats_persistent=on),使用参数innodb_stats_persistent_sample_pages的值,来采样,此时非持久化的参数innodb_stats_sample_pages就无效。

From 5.6.6 开始,使用非持久化的统计信息:

1.set innodb_stats_persistent=0;

2.create|alter table stats_persistent=0;

对单个表开启:

create|alter table...STATS_PERSISTENT [=] {DEFAULT|0|1}
登入後複製

DEFAULT:table的统计信息是否持久化由参数 innodb_stats_persistent 决定。\

总结:From 5.6.6 开始,要么开启统计信息持久化,要么是还用以前的非持久化,二者选一。


参考相关参数:

innodb_stats_method: nulls_equalnulls_unequal, and nulls_ignored
myisam_stats_method:nulls_equalnulls_unequal, and nulls_ignored

<span style="font-size:19px;">--------------------------------------------------------------</span>

<span style="color:#488CF2;">基数即value group=N/s (N:表行数 S:average group size)<br>基数(VG)|值组为不重复的值的个数<br></span>

<span style="color:#488CF2;">nulls_equal:所有的NULL都相等,算作一个值组,这样一旦null值很多的情况下,<span style="font-size:13.6000003814697px;line-height:25.2000007629395px;">average group size偏大,导致基数偏小。</span></span>

<span style="color:#488CF2;">nulls_unequal:<span style="font-size:13.6000003814697px;line-height:25.2000007629395px;">每一个NULL都相等,算作一个值组,这样一旦null值很多的情况下,如果non-null值组大,而null的值组过多,导致average group size偏小,导致基数偏大,可能导致误走索引</span></span>

<span style="color:#488CF2;">nulls_ignored:所有的null都忽略,不记录索引。</span>

<span style="font-size:19px;">--------------------------------------------------------------</span>

参考:

# http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_stats_method

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

H5頁面製作是否需要持續維護 H5頁面製作是否需要持續維護 Apr 05, 2025 pm 11:27 PM

H5頁面需要持續維護,這是因為代碼漏洞、瀏覽器兼容性、性能優化、安全更新和用戶體驗提升等因素。有效維護的方法包括建立完善的測試體系、使用版本控制工具、定期監控頁面性能、收集用戶反饋和製定維護計劃。

在router文件夾下的index.js文件中為什麼需要調用Vue.use(VueRouter)? 在router文件夾下的index.js文件中為什麼需要調用Vue.use(VueRouter)? Apr 05, 2025 pm 01:03 PM

在router文件夾下的index.js文件中註冊VueRouter的必要性在開發Vue應用程序時,常常會遇到關於路由配置的問題。特�...

沒有H5,JS能運行嗎? 沒有H5,JS能運行嗎? Apr 06, 2025 am 09:06 AM

JavaScript 是否可在無 HTML5 環境下運行? JavaScript 引擎自身可獨立運行。在瀏覽器環境中運行 JavaScript 依賴 HTML5,因其提供加載和執行代碼所需的標準化環境。 HTML5 提供的 API 和特性對現代 JavaScript 框架和庫至關重要。離開 HTML5 環境,許多 JavaScript 功能難以實現或無法實現。

為什麼Flex佈局中的紫色斜線區域會被誤認為是'溢出空間”? 為什麼Flex佈局中的紫色斜線區域會被誤認為是'溢出空間”? Apr 05, 2025 pm 05:51 PM

關於Flex佈局中紫色斜線區域的疑問在使用Flex佈局時,你可能會遇到一些令人困惑的現象,比如在開發者工具(d...

H5頁面製作的優勢有哪些 H5頁面製作的優勢有哪些 Apr 05, 2025 pm 11:48 PM

H5 頁面製作的優勢包括:輕量級體驗,加載速度快,提升用戶留存率。跨平台兼容性,無需針對不同平台適配,提升開發效率。靈活性和動態更新,無需審核,便於內容修改和更新。成本效益,開發成本比原生 App 低。

為什麼在Safari中自定義樣式表能在本地網頁生效,但在百度頁面上卻無法生效? 為什麼在Safari中自定義樣式表能在本地網頁生效,但在百度頁面上卻無法生效? Apr 05, 2025 pm 05:15 PM

在Safari中使用自定義樣式表的問題探討今天我們來探討一個關於Safari瀏覽器的自定義樣式表應用問題。前端新手...

無法以 root 身份登錄 mysql 無法以 root 身份登錄 mysql Apr 08, 2025 pm 04:54 PM

無法以 root 身份登錄 MySQL 的原因主要在於權限問題、配置文件錯誤、密碼不符、socket 文件問題或防火牆攔截。解決方法包括:檢查配置文件中 bind-address 參數是否正確配置。查看 root 用戶權限是否被修改或刪除,並進行重置。驗證密碼是否準確無誤,包括大小寫和特殊字符。檢查 socket 文件權限設置和路徑。檢查防火牆是否阻止了 MySQL 服務器的連接。

為什麼Edge瀏覽器中的特定div元素無法顯示?如何解決這個問題? 為什麼Edge瀏覽器中的特定div元素無法顯示?如何解決這個問題? Apr 05, 2025 pm 08:21 PM

如何解決用戶代理樣式表導致的顯示問題?在使用Edge瀏覽器時,項目中的一個div元素無法顯示。經過查看,發�...

See all articles