溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

MySQL中的統(tǒng)計信息相關(guān)參數(shù)介紹

發(fā)布時間:2020-08-13 05:34:39 來源:ITPUB博客 閱讀:208 作者:沃趣科技 欄目:MySQL數(shù)據(jù)庫

統(tǒng)計信息的作用


上周同事在客戶現(xiàn)場遇到了由于統(tǒng)計信息的原因,導(dǎo)致應(yīng)用數(shù)據(jù)遷移時間過慢,整個遷移差點失敗。關(guān)鍵時刻同事發(fā)現(xiàn)測試環(huán)境與生產(chǎn)環(huán)境SQL語句執(zhí)行計劃不一致,立刻收集統(tǒng)計信息才保證遷移得以正常完成。 
統(tǒng)計信息對于SQL的執(zhí)行時間有重要的影響,統(tǒng)計信息的不準(zhǔn)確會導(dǎo)致SQL的執(zhí)行計劃不準(zhǔn)確,從而致使SQL執(zhí)行時間變慢,Oracle DBA非常了解統(tǒng)計信息的收集規(guī)則,同樣在MySQL中也有相關(guān)的參數(shù)去控制統(tǒng)計信息。


相關(guān)參數(shù)



innodb_stats_auto_recalc

控制innodb是否自動收集統(tǒng)計信息,默認是打開的。當(dāng)表中數(shù)據(jù)變化超過%10時候,就會重新計算統(tǒng)計信息。參數(shù)的生效依賴于建表時指定innodb_stats_persistent是打開的或CREATE TABLE , ALTER TABLE 時指定STATS_PERSISTENT=1采樣page的個數(shù)通過參數(shù)innodb_stats_persistent_sample_pages來控制。

  • 測試驗證

創(chuàng)建一張測試表,并在表上創(chuàng)建一個索引:

create table dhytest (id int) STATS_PERSISTENT=1; create index idx_id on dhytest(id); 

通過mysql.innodb_index_stats可以查看索引最后收集統(tǒng)計信息的時間,這里的聚集索引我們刪除先不用去看,只看自己創(chuàng)建的二級索引

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:37:43]>select * from mysql.innodb_index_stats where database_name = 'test';
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+ | database_name | table_name | index_name      | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+ | test          | dhytest    | idx_id          | 2017-07-10 22:36:06 | n_diff_pfx01 |          0 |           1 | id                                |
| test          | dhytest    | idx_id          | 2017-07-10 22:36:06 | n_diff_pfx02 |          0 |           1 | id,DB_ROW_ID                      |
| test          | dhytest    | idx_id          | 2017-07-10 22:36:06 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| test          | dhytest    | idx_id          | 2017-07-10 22:36:06 | size         |          1 |        NULL | Number of pages in the index      |
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+ 7 rows in set (0.00 sec) 

我們手工往表中插入數(shù)據(jù),讓數(shù)據(jù)的變化超過%10

 [root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:37:56]>insert into dhytest values (10);
Query OK, 1 row affected (0.00 sec)

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:38:17]>insert into dhytest select * from dhytest;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:38:28]>insert into dhytest select * from dhytest;
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:38:31]>insert into dhytest select * from dhytest;
Query OK, 4 rows affected (0.01 sec)
Records: 4  Duplicates: 0  Warnings: 0

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:38:34]>insert into dhytest select * from dhytest;
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:38:35]>insert into dhytest select * from dhytest;
Query OK, 16 rows affected (0.00 sec)
Records: 16  Duplicates: 0  Warnings: 0 

這時我們在查看下mysql.innodb_index_stats表,last_update時間發(fā)生了變化

	

[root@shadow:/root 5.7.18-log_Instance1 root@localhost:test 22:38:36]>select * from mysql.innodb_index_stats where database_name = 'test'; +---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+ | database_name | table_name | index_name      | last_update         | stat_name    | stat_value | sample_size | stat_description                  | +---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+ | test          | dhytest    | idx_id          | 2017-07-10 22:38:28 | n_diff_pfx01 |          1 |           1 | id                                | | test          | dhytest    | idx_id          | 2017-07-10 22:38:28 | n_diff_pfx02 |          2 |           1 | id,DB_ROW_ID                      | | test          | dhytest    | idx_id          | 2017-07-10 22:38:28 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index | | test          | dhytest    | idx_id          | 2017-07-10 22:38:28 | size         |          1 |        NULL | Number of pages in the index      | +---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+ 7 rows in set (0.00 sec)


innodb_stats_persistent


控制是否將統(tǒng)計信息持久到磁盤當(dāng)中,設(shè)置此參數(shù)之后我們就不需要實時去收集統(tǒng)計信息了,因為實時收集統(tǒng)計信息在高并發(fā)下可能會造成一定的性能上影響,并且會導(dǎo)致執(zhí)行計劃有所不同。建議是將此參數(shù)打開,將innodb_stats_auto_recalc參數(shù)進行關(guān)閉。



innodb_stats_persistent_sample_pages


控制收集統(tǒng)計信息時采樣的page數(shù)量,默認是20。收集的page數(shù)量越多,每次收集統(tǒng)計信息的實際則越長,但是統(tǒng)計信息也相對比較準(zhǔn)確。

我們可以在創(chuàng)建表的時候?qū)Σ煌谋碇付ú煌膒age數(shù)量、是否將統(tǒng)計信息持久化到磁盤上、是否自動收集統(tǒng)計信息

	

CREATE TABLE `t1` ( `id` int(8) NOT NULL auto_increment, `data` varchar(255), `date` datetime, PRIMARY KEY  (`id`), INDEX `DATE_IX` (`date`) ) ENGINE=InnoDB,  STATS_PERSISTENT=1,  STATS_AUTO_RECALC=1,  STATS_SAMPLE_PAGES=25;


innodb_stats_on_metadata


此參數(shù)在5.6.5版本之前是默認開啟的,設(shè)置此參數(shù)后當(dāng)我們執(zhí)行show index 或者 show table status 或者訪問INFORMATION_SCHEMA.TABLES or INFORMATION_SCHEMA.STATISTICS表時就會收集統(tǒng)計信息,但是這樣可能會導(dǎo)致執(zhí)行計劃改變。 

在以前當(dāng)表中記錄變化超過1/16就會收集統(tǒng)計信息,但是現(xiàn)在如果設(shè)置了innodb_stats_persistent就不會有這樣的說法了。

MySQL中的統(tǒng)計信息相關(guān)參數(shù)介紹

innodb_stats_include_delete_marked


5.6.35版本中新增的參數(shù),就是在未提交的事務(wù)中如果我們刪除了記錄,收集統(tǒng)計信息的時候是排查這些刪除了的記錄的。這樣就可能導(dǎo)致統(tǒng)計信息并不是很準(zhǔn)確,設(shè)置此參數(shù)之后就是收集統(tǒng)計信息的時候包含未提交事務(wù)中被標(biāo)記為已刪除的數(shù)據(jù)。


innodb_stats_method


控制統(tǒng)計信息針對索引中NULL值的算法 

當(dāng)設(shè)置為nulls_equal 所有的NULL值都視為一個value group 
當(dāng)設(shè)置為nulls_unequal每一個NULL值被視為一個value group 
設(shè)置為nulls_ignored時 NULL值被忽略 

這個參數(shù)同事彭許生做過一些測試發(fā)現(xiàn)nulls_equal和nulls_unequal沒有發(fā)現(xiàn)show index中的cardinality有不同的地方,但是如果設(shè)置為nulls_ignored的時候會有所不同。

  • 測 試

表結(jié)構(gòu)數(shù)據(jù)

MySQL中的統(tǒng)計信息相關(guān)參數(shù)介紹

設(shè)置為nulls_ignored

MySQL中的統(tǒng)計信息相關(guān)參數(shù)介紹

設(shè)置為nulls_unequal

MySQL中的統(tǒng)計信息相關(guān)參數(shù)介紹

設(shè)置為nulls_equal

MySQL中的統(tǒng)計信息相關(guān)參數(shù)介紹


推薦配置

  • innodb_stats_method 統(tǒng)計信息的自動收集在高并發(fā)情況下可能會帶來性能的抖動,建議將此參數(shù)關(guān)閉。 

  • innodb_stats_persistent 建議打開此參數(shù)將統(tǒng)計信息持久化到磁盤上 。

  • innodb_stats_include_delete_marked建議設(shè)置開啟,這樣可以針對未提交事務(wù)中刪除的數(shù)據(jù)也收集統(tǒng)計信息 。

  • innodb_stats_method經(jīng)過測試和mos查看到的按默認配置就可以,當(dāng)然如果設(shè)置nulls_ignored時候會讓你的語句走到索引,但是效率并不一定是好的。

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI