1 查詢表的統計信息
information_schema.tables?是 MySQL 中的一個系統視圖,包含數據庫中所有表的信息。
如何查詢當前數據庫的所有表信息:
SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();
返回的字段有:
字段名 | 含義 |
TABLE_CATALOG | 表所屬的目錄名,通常為 'def'(默認) |
TABLE_SCHEMA | 表所屬的數據庫名 |
TABLE_NAME | 表名 |
TABLE_TYPE | 表類型:'BASE TABLE'(普通表)或 'VIEW'(視圖) |
ENGINE | 存儲引擎(如 InnoDB、MyISAM) |
VERSION | 版本信息(通常為10) |
ROW_FORMAT | 行格式(Compact、Dynamic等) |
TABLE_ROWS | 行數(InnoDB為估算值,不精確) |
AVG_ROW_LENGTH | 平均行長度(字節) |
DATA_LENGTH | 數據總長度(字節) |
MAX_DATA_LENGTH | 最大數據長度(字節) |
INDEX_LENGTH | 索引總長度(字節) |
DATA_FREE | 已分配但未使用的空間(字節) |
AUTO_INCREMENT | 下一個AUTO_INCREMENT值(可能為NULL) |
CREATE_TIME | 表創建時間 |
UPDATE_TIME | 表最后更新時間(對InnoDB可能為NULL) |
CHECK_TIME | 最后檢查時間(對MyISAM) |
TABLE_COLLATION | 表的默認字符集和排序規則(如utf8mb4_unicode_ci) |
CHECKSUM | 校驗和值(如果啟用) |
CREATE_OPTIONS | 創建表時的額外選項 |
TABLE_COMMENT | 表注釋 |
那么我們就可以獲取我們感興趣的表信息,比如:
-- 查詢?table1?表的行數、數據長度、創建時間
SELECTtable_name,table_rows,(data_length+index_length)/1024/1024 AS sizeMB,create_time
FROM information_schema.tables
WHEREtable_schema = DATABASE()AND table_name='table1';
2 InnoDB 的自動統計機制
(1)非實時性
你會發現,當你向表中插入一批數據后,再查詢 information_schema.tables 信息,其行數、數據長度等值并沒有改變。
這是由于 MySQL 的統計信息并不是實時的,InnoDB 存儲引擎為了提高性能、減少對數據庫操作的影響,采用了異步統計信息收集機制,我們查詢到的信息并不能表示表當前的實時狀態。
統計信息的刷新時機:
- 第一次打開一個表時
- 當執行某些 DDL 操作時(如創建索引、重建表等)
- 當超過一定時間或數據變化達到一定比例時(由參數控制)
(2)非精確性
同時, InnoDB 采用采樣的方式來估計這些統計數據,而不是每次都進行精確計算,所以統計信息本身存在一定的誤差。
可以查看統計信息更新的相關參數:
SHOW VARIABLES LIKE 'innodb_stats%';
關鍵參數:
- innodb_stats_auto_recalc:是否啟用自動重新計算(默認 ON)
- innodb_stats_persistent:是否持久化統計信息(默認 ON,8.0+)
- innodb_stats_persistent_sample_pages:采樣頁數(默認 20), 增加此值可以提高統計信息的準確性,但也會增加計算成本
- innodb_stats_transient_sample_pages:非持久化統計的采樣頁數
- innodb_stats_on_metadata:在 SHOW TABLE STATUS、SHOW INDEX、查詢?information_schema.tables?等元數據時,是否觸發統計信息的更新(默認OFF)
(3)如何獲取更接近實時的統計信息
可以通過執行 ANALYZE TABLE 命令來強制刷新統計信息。不過需要注意,這可能會對正在運行的查詢產生影響(尤其對大型表),因此在生產環境謹慎使用。Is ANALYZE TABLE Safe on a Busy MySQL Database Server?
ANALYZE TABLE table1;
?