确认统计信息失效需三步:EXPLAIN看type是否ALL、key是否NULL;对比rows预估与COUNT(*)实际值,偏差超10倍即失真;查STATISTICS表Cardinality与COUNT(DISTINCT)是否严重不符。

备份还原后统计信息失效,不是“丢了”,而是“没更新”——InnoDB 的统计信息(Cardinality、行数估算等)在还原过程中不会自动重建,优化器仍沿用旧采样结果,导致执行计划错乱,比如该走索引却选了全表扫描。
怎么确认是统计信息失效,而不是索引被删或SQL写错
别急着改SQL或重建索引,先看三件事:
- 执行
EXPLAIN SELECT ...,检查type是否为ALL、key是否为NULL;如果索引明明存在、字段类型也匹配(比如status是TINYINT,WHERE 里没传字符串'1'),但还是没走索引,就不是语法或定义问题 - 对比
rows预估值和实际扫描量:若预估 120 行,SELECT COUNT(*)却返回 80 万行,偏差超 10 倍,基本锁定统计失真 - 查
information_schema.STATISTICS中该列的Cardinality,再手动跑COUNT(DISTINCT your_col);比如状态字段只有0/1/2三个值,Cardinality却显示 1567,说明采样完全失准
ANALYZE TABLE 执行后为什么还是慢
ANALYZE TABLE 不是万能按钮,它受配置和数据分布双重制约:
- 大表默认只采样 20 页(
innodb_stats_persistent_sample_pages = 20),千万行以上极易不准;必须提前调高:SET GLOBAL innodb_stats_persistent_sample_pages = 128 - 极端偏态列(如 95% 值为
1的is_deleted)需强制全量:ANALYZE TABLE t1 WITH SAMPLE 100 PERCENT - 还原后若未显式执行
ANALYZE TABLE,InnoDB 不会自动触发——它的自动更新阈值是“修改行数 ≥ 当前表总行数 × 10%”,一张 5000 万行的表得改满 500 万行才动,业务根本等不到 - MySQL 5.7 升 8.0+ 后,优化器更严格,旧统计立刻暴露;必须确认
innodb_stats_persistent = ON(升级后配置文件可能残留OFF)
还原后连接数飙升,其实也是统计信息惹的祸
表面是连接堆积,根子常在慢查询引发的锁等待或长事务卡住:
-
SHOW FULL PROCESSLIST中看到大量State = Sending data或Sorting result,且Time持续上涨,大概率是执行计划崩了,正在扫几十万行 -
Threads_running很低但Threads_connected接近max_connections,说明连接池在反复建连——因为上一个查询太慢,超时释放失败,应用误判为连接异常而新建 - MyISAM 表还原后可能损坏(
CHECK TABLE显示status: crash),查询直接 hang 住,连接卡死在Sleep状态不释放 - 还原覆盖了
wait_timeout,但应用连接池的idle-timeout没同步调整,造成“MySQL 想断,应用还想用”的僵持
统计信息这东西看不见摸不着,但它一歪,所有查询都跟着偏航;还原后不跑 ANALYZE TABLE,等于开着蒙眼车下高速——出事不是概率问题,是时间问题。


















