如何通过Analyze Table更新采样优化MySQL多列复合索引的基数统计?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1225个文字,预计阅读时间需要5分钟。
MySQL的优化器依赖于列的基数(cardinality)来选择索引。复合索引的基数统计不是针对每个组合值单独计数,而是基于采样估算的——默认情况下,仅采样10个数据页(由innodb_stats_sample_pages控制),仅对前缀列做统计。如果表很大、数据倾斜严重,或复合索引列的顺序与查询条件不匹配,那么ANALYZE TABLE可能无法准确更新你关心的列组合的统计值。
实操建议:
- 先查当前统计是否真的被更新:
SHOW INDEX FROM your_table;关注
Cardinality列,对比ANALYZE TABLE前后变化 - 确认采样页数是否足够:运行
SELECT @@innodb_stats_sample_pages;,小表可保持默认,大表(千万级以上)建议设为
100或200(需在配置文件或会话中设置并重启生效) -
ANALYZE TABLE不触发即时重算——InnoDB 实际使用的是持久化统计信息(innodb_stats_persistent = ON默认开启),它只在表首次打开、DDL 后或显式调用时刷新,但不会自动重采样所有列组合
复合索引的基数到底统计哪几列
MySQL 对复合索引 (a, b, c) 的基数统计是分层的:只统计 a、(a,b)、(a,b,c) 这三个前缀组合,**不会统计 b 单独、(b,c) 或 c 的基数**。
本文共计1225个文字,预计阅读时间需要5分钟。
MySQL的优化器依赖于列的基数(cardinality)来选择索引。复合索引的基数统计不是针对每个组合值单独计数,而是基于采样估算的——默认情况下,仅采样10个数据页(由innodb_stats_sample_pages控制),仅对前缀列做统计。如果表很大、数据倾斜严重,或复合索引列的顺序与查询条件不匹配,那么ANALYZE TABLE可能无法准确更新你关心的列组合的统计值。
实操建议:
- 先查当前统计是否真的被更新:
SHOW INDEX FROM your_table;关注
Cardinality列,对比ANALYZE TABLE前后变化 - 确认采样页数是否足够:运行
SELECT @@innodb_stats_sample_pages;,小表可保持默认,大表(千万级以上)建议设为
100或200(需在配置文件或会话中设置并重启生效) -
ANALYZE TABLE不触发即时重算——InnoDB 实际使用的是持久化统计信息(innodb_stats_persistent = ON默认开启),它只在表首次打开、DDL 后或显式调用时刷新,但不会自动重采样所有列组合
复合索引的基数到底统计哪几列
MySQL 对复合索引 (a, b, c) 的基数统计是分层的:只统计 a、(a,b)、(a,b,c) 这三个前缀组合,**不会统计 b 单独、(b,c) 或 c 的基数**。

