ANALYZE 是什么
ANALYZE 收集表的统计信息——列值分布、空值比例、区分度,优化器依赖这些数据估算行数并选择访问路径。大批量导入或删除后,统计信息与现实明显脱节,计划就会变差,这时先 ANALYZE 再考虑改写 SQL 或加索引。PostgreSQL 的 ANALYZE 只读取样本、不阻塞读写,可以随时执行;autovacuum 也会按变更比例自动触发 autoanalyze,但瞬时大批量写入后建议手动补一次,别等自动任务周期。
基本信息
| 适用平台 | PostgreSQL(MySQL 的对应语句是 ANALYZE TABLE,重新统计索引基数) |
|---|---|
| 语法 | ANALYZE [VERBOSE] 表名;不带表名则分析当前库所有表 |
| 采样精度 | default_statistics_target 默认 100,可按列单独提高关键列的精度 |
| 自动触发 | autovacuum_analyze_scale_factor 与 autovacuum_analyze_threshold |
| 多列相关性 | 列间强相关(城市与邮编)时用 CREATE STATISTICS 建扩展统计 |
| 查看状态 | pg_stat_user_tables 里的 last_analyze、last_autoanalyze、n_mod_since_analyze |
典型使用场景
- 大批量导入或删除后补齐统计信息
- 计划突然变差、估算行数与实际差很多时先 ANALYZE 排除统计问题
- 定期维护任务里固定执行一次,配合 VACUUM
- 分区表逐分区分析,避免父表统计滞后
- 关键列区分度高时提高采样精度,让估算更贴近真实分布
执行与查看
执行与查看
ANALYZE orders; # 收集单表统计
ANALYZE VERBOSE orders; # 输出处理进度
-- 查看最近一次统计收集时间与未分析变更量
SELECT relname, last_analyze, last_autoanalyze,
n_live_tup, n_mod_since_analyze
FROM pg_stat_user_tables
WHERE relname = 'orders';
-- 提高关键列采样精度后再分析,让估算更准
ALTER TABLE orders ALTER COLUMN user_id SET STATISTICS 500;
ANALYZE orders;批量导入后的标准动作
批量导入后的标准动作
-- 导入完成后立刻补统计,避免优化器沿用旧分布
COPY orders FROM '/tmp/orders.csv' WITH (FORMAT csv, HEADER true);
ANALYZE orders;
-- 需要多列相关性时先建扩展统计
CREATE STATISTICS st_orders_city_zip (dependencies)
ON city, zip FROM orders;
ANALYZE orders;关键点速查
| 项目 | 说明 | 注意 |
|---|---|---|
| 执行成本 | 只读样本,不阻塞读写 | 可随时执行,大表采样量受参数控制 |
| 采样量 | default_statistics_target | 关键列可单独提高精度 |
| 自动触发 | autovacuum 的 autoanalyze | 按变更比例触发,瞬时大批量后可能来不及 |
| 多列相关性 | CREATE STATISTICS | 城市与邮编这类强相关列 |
| 状态查看 | pg_stat_user_tables | 关注 last_analyze 与 n_mod_since_analyze |
ANALYZE 与 VACUUM 不是同一件事:前者更新统计信息让估算更准,后者回收死元组占用的空间;维护任务里两者通常都跑,但触发条件与代价不同。
导入几百万行后不执行 ANALYZE,优化器仍按旧分布选择计划,可能持续走错访问方式;建议把 ANALYZE 作为批量写入脚本的固定收尾步骤。