統計信息概念 MySQL統計信息是指資料庫通過採樣、統計出來的表、索引的相關信息,例如,表的記錄數、聚集索引page個數、欄位的Cardinality....。MySQL在生成執行計劃時,需要根據索引的統計信息進行估算,計算出最低代價(或者說是最小開銷)的執行計劃.MySQL支持有限的索引統計信息,... ...
統計信息概念
MySQL統計信息是指資料庫通過採樣、統計出來的表、索引的相關信息,例如,表的記錄數、聚集索引page個數、欄位的Cardinality....。MySQL在生成執行計劃時,需要根據索引的統計信息進行估算,計算出最低代價(或者說是最小開銷)的執行計劃.MySQL支持有限的索引統計信息,因存儲引擎不同而統計信息收集的方式也不同. MySQL官方關於統計信息的概念介紹幾乎等同於無,不過對於已經接觸過其它類型資料庫的同學而言,理解這個概念應該不在話下。相對於其它資料庫而言,MySQL統計信息無法手工刪除。MySQL 8.0之前的版本,MySQL是沒有直方圖的。
統計信息參數
MySQL的InnoDB存儲引擎的統計信息參數有7(個別版本有8個之多),如下所示:
MySQL 5.6.41 有8個參數:
mysql> show variables like 'innodb_stats%';
+--------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------+-------------+
| innodb_stats_auto_recalc | ON |
| innodb_stats_include_delete_marked | OFF |
| innodb_stats_method | nulls_equal |
| innodb_stats_on_metadata | OFF |
| innodb_stats_persistent | ON |
| innodb_stats_persistent_sample_pages | 20 |
| innodb_stats_sample_pages | 8 |
| innodb_stats_transient_sample_pages | 8 |
+--------------------------------------+-------------+
8 rows in set (0.00 sec)
MySQL 8.0.18 有7個參數:
mysql> show variables like 'innodb_stats%';
+--------------------------------------+-------------+
| Variable_name | Value |
+--------------------------------------+-------------+
| innodb_stats_auto_recalc | ON |
| innodb_stats_include_delete_marked | OFF |
| innodb_stats_method | nulls_equal |
| innodb_stats_on_metadata | OFF |
| innodb_stats_persistent | ON |
| innodb_stats_persistent_sample_pages | 20 |
| innodb_stats_transient_sample_pages | 8 |
+--------------------------------------+-------------+
關於這些參數的功能,下麵做了一個大概的整理、收集。
參數名稱 |
參數意義 |
innodb_stats_auto_recalc |
是否自動觸發更新統計信息。當被修改的數據超過10%時就會觸發統計信息重新統計計算 |
innodb_stats_include_delete_marked |
控制在重新計算統計信息時是否會考慮刪除標記的記錄。 |
innodb_stats_method |
對null值的統計方法 |
innodb_stats_on_metadata |
操作元數據時是否觸發更新統計信息 |
innodb_stats_persistent |
統計信息是否持久化 |
innodb_stats_sample_pages |
不推薦使用,已經被innodb_stats_persistent_sample_pages替換 |
innodb_stats_persistent_sample_pages |
持久化抽樣page數 |
innodb_stats_transient_sample_pages |
瞬時抽樣page數 |
參數innodb_stats_auto_recalc
該參數innodb_stats_auto_recalc控制是否自動重新計算統計信息,當表中數據有大於10%被修改時就會重新計算統計信息(註意,由於統計信息重新計算是在後臺發生,而且它是非同步處理,這個可能存在延時,不會立即觸發,具體見下麵介紹)。如果關閉了innodb_stats_auto_recalc,需要通過analyze table來保證統計信息的準確性。不管有沒有開啟全局變數innodb_stats_auto_recalc。即使innodb_stats_auto_recalc=OFF時,當新索引被增加到表中,所有索引的統計信息會被重新計算並且更新到innodb_index_stats表上。
下麵驗證一下系統變數innodb_stats_auto_recalc=OFF時,創建索引時,會觸發該表所有索引重新統計計算。
mysql> set global innodb_stats_auto_recalc=off;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'innodb_stats_auto_recalc%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_stats_auto_recalc | OFF |
+--------------------------+-------+
1 row in set (0.00 sec)
mysql> select * from mysql.innodb_index_stats
-> where database_name='MyDB' and table_name = 'test';
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update | stat_name | stat_value | sample_size | stat_description |
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+
| MyDB | test | GEN_CLUST_INDEX | 2019-10-28 14:54:48 | n_diff_pfx01 | 2 | 1 | DB_ROW_ID |
| MyDB | test | GEN_CLUST_INDEX | 2019-10-28 14:54:48 | n_leaf_pages | 1 | NULL | Number of leaf pages in the index |
| MyDB | test | GEN_CLUST_INDEX | 2019-10-28 14:54:48 | size | 1 | NULL | Number of pages in the index |
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+
3 rows in set (0.00 sec)
mysql> create index ix_test_name on test(name);
mysql> select * from mysql.innodb_index_stats
-> where database_name='MyDB' and table_name = 'test';
+---------------+------------+-----------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update &n