必须手动执行analyze table,因为基表大批量dml后统计信息未及时更新,导致优化器误判索引选择性,视图查询被迫全表扫描。

视图本身不需要刷新,但它的执行计划依赖的统计信息会失效——不手动 ANALYZE,查询可能变慢甚至崩掉。
为什么改了百万行数据,视图查询突然变慢?
视图只是封装了 SELECT 语句,每次执行都重跑底层 SQL;但它用的执行计划,由优化器根据 mysql.innodb_table_stats 或 pg_class.reltuples 这类统计信息生成。基表大批量 DML 后,这些数字不会自动更新,导致优化器误判:比如以为某索引只覆盖 10 行,实际已有 50 万行匹配,结果放弃走索引、硬上全表扫描。
- MySQL:
innodb_stats_auto_recalc默认开启,但触发阈值是“变更行数 > 表总行数 × 10%”,且仅对 InnoDB 表生效;批量导入或TRUNCATE + INSERT后它根本不会触发 - PostgreSQL:自动分析由
autovacuum_analyze_threshold和autovacuum_analyze_scale_factor控制,默认是“改动行数 > 50 + 当前行数 × 10%”,大表(如 1 亿行)要改超 1000 万行才触发,明显滞后 - SQL Server:自动更新只在查询时“按需采样”,且默认采样率低(约 1–5%),面对倾斜分布或新增大量重复值(如 status = 'pending' 批量插入),直方图严重失真
哪些操作后必须立刻 ANALYZE?
不是所有 DML 都需要,但以下场景下,不手动跑 ANALYZE TABLE(MySQL)、VACUUM ANALYZE(PostgreSQL)或 UPDATE STATISTICS(SQL Server),后续查视图极大概率出问题:
- 刚用
LOAD DATA INFILE或COPY导入 >5% 总行数的新数据 - 执行过
DELETE FROM t WHERE created_at 这类范围清理,删掉大量旧记录 - ALTER TABLE 新增/删除列、重建索引后,新对象无统计信息(
SHOW INDEX FROM t中Cardinality为 0) - EXPLAIN 显示
rows估算值和实际COUNT(*)相差 3 倍以上,尤其出现在 JOIN 或 WHERE 条件字段上
ANALYZE 要不要加 CONCURRENTLY?
不能一概而论:
- PostgreSQL 的
ANALYZE默认不锁表,但若同时跑大量写入,I/O 压力会升高;ANALYZE CONCURRENTLY并不存在——那是给REFRESH MATERIALIZED VIEW用的 - MySQL 的
ANALYZE TABLE会加MDL_SHARED_NO_WRITE锁,阻塞 DDL 和部分 DML,大表建议在低峰期执行;可临时调高innodb_stats_sample_pages提升采样精度,但别设到 200 以上,否则 I/O 拖垮实例 - SQL Server 的
UPDATE STATISTICS ... WITH FULLSCAN最准但最慢,日常用WITH SAMPLE 20 PERCENT更平衡;注意别在从库上跑,主从统计信息应保持一致
真正容易被忽略的是:视图里嵌套了多层 JOIN 或子查询时,单张基表的统计失真会指数级放大执行计划错误。哪怕只有一张表没 ANALYZE,整个视图的性能就可能断崖下跌——这不是视图的问题,是统计信息没跟上数据节奏。











