如何通过执行Analyze命令更新SQL大表修改后的统计信息?
- 内容介绍
- 相关推荐
本文共计702个文字,预计阅读时间需要3分钟。
许多数据库(如PostgreSQL、MySQL 8.0的InnoDB)在执行UPDATE、DELETE或INSERT操作后,不会自动触发系统计信信息刷新。优化器依赖的行数估算、列值分布、直方图等,可能需要手动执行ANALYZE命令更新。若修改量超过表总行数的10%-20%,执行计划就可能优化不当——例如,本应走索引却选择了全表扫描。
什么时候必须手动执行 ANALYZE
以下情况建议立即运行 ANALYZE:
- 单次修改了 >5% 的数据行(例如对千万级表
UPDATE百万行) - 新增或删除了大量重复值(如批量填充某字段为相同状态码)
- 执行完
VACUUM FULL或CLUSTER(PostgreSQL)后 - 查询响应时间突增,且
EXPLAIN显示预估行数偏差 >10 倍
ANALYZE 的实际执行要点
直接运行 ANALYZE 是安全的:它只读取数据、不锁表(PostgreSQL)、不阻塞 DML;但耗时与采样量正相关。关键控制点:
- 默认只采样约 300 行(PostgreSQL),对大表完全不够——需显式指定列或调整
default_statistics_target - 可针对单列分析:
ANALYZE table_name (column_a, column_b),比全表快且更精准 - MySQL 中对应命令是
ANALYZE TABLE table_name,但仅更新索引基数,不生成直方图(需CREATE STATISTICS配合) - 避免在业务高峰执行全表
ANALYZE;若表超 1 亿行,优先用ANALYZE table_name (col) WITH (sample_rate = 0.05)(PostgreSQL 15+)
常见误操作和副作用
不是所有“重统计”都叫 ANALYZE,混淆会导致白忙活:
- 把
VACUUM当成统计更新——它只清理死元组,不更新统计信息(PostgreSQL) - 在 MySQL 5.7 执行
ANALYZE TABLE后仍慢?因为默认关闭直方图,需先设set global histogram_generation_enabled = on - PostgreSQL 中
ANALYZE不会更新pg_class.reltuples的精确值,它仍是估算值;真正精确行数得查SELECT COUNT(*) - 某些 ORM(如 Django 的
bulk_update)批量改完不触发ANALYZE,得在应用层补调用或加定时任务
统计信息不是越新越好,也不是越多越准——关键是让优化器对「最常被 WHERE / JOIN 用到的列」有合理分布认知。盲目全表高频 ANALYZE 可能拖慢系统,而漏掉关键列又会让执行计划崩盘。
本文共计702个文字,预计阅读时间需要3分钟。
许多数据库(如PostgreSQL、MySQL 8.0的InnoDB)在执行UPDATE、DELETE或INSERT操作后,不会自动触发系统计信信息刷新。优化器依赖的行数估算、列值分布、直方图等,可能需要手动执行ANALYZE命令更新。若修改量超过表总行数的10%-20%,执行计划就可能优化不当——例如,本应走索引却选择了全表扫描。
什么时候必须手动执行 ANALYZE
以下情况建议立即运行 ANALYZE:
- 单次修改了 >5% 的数据行(例如对千万级表
UPDATE百万行) - 新增或删除了大量重复值(如批量填充某字段为相同状态码)
- 执行完
VACUUM FULL或CLUSTER(PostgreSQL)后 - 查询响应时间突增,且
EXPLAIN显示预估行数偏差 >10 倍
ANALYZE 的实际执行要点
直接运行 ANALYZE 是安全的:它只读取数据、不锁表(PostgreSQL)、不阻塞 DML;但耗时与采样量正相关。关键控制点:
- 默认只采样约 300 行(PostgreSQL),对大表完全不够——需显式指定列或调整
default_statistics_target - 可针对单列分析:
ANALYZE table_name (column_a, column_b),比全表快且更精准 - MySQL 中对应命令是
ANALYZE TABLE table_name,但仅更新索引基数,不生成直方图(需CREATE STATISTICS配合) - 避免在业务高峰执行全表
ANALYZE;若表超 1 亿行,优先用ANALYZE table_name (col) WITH (sample_rate = 0.05)(PostgreSQL 15+)
常见误操作和副作用
不是所有“重统计”都叫 ANALYZE,混淆会导致白忙活:
- 把
VACUUM当成统计更新——它只清理死元组,不更新统计信息(PostgreSQL) - 在 MySQL 5.7 执行
ANALYZE TABLE后仍慢?因为默认关闭直方图,需先设set global histogram_generation_enabled = on - PostgreSQL 中
ANALYZE不会更新pg_class.reltuples的精确值,它仍是估算值;真正精确行数得查SELECT COUNT(*) - 某些 ORM(如 Django 的
bulk_update)批量改完不触发ANALYZE,得在应用层补调用或加定时任务
统计信息不是越新越好,也不是越多越准——关键是让优化器对「最常被 WHERE / JOIN 用到的列」有合理分布认知。盲目全表高频 ANALYZE 可能拖慢系统,而漏掉关键列又会让执行计划崩盘。

