explain 里 rows 估 120,实际扫描 40 万行,慢查询里 Rows_examined 也是四十万。同一条 SQL 前一天还是 30 毫秒。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
ANALYZE TABLE orders; EXPLAIN SELECT id FROM orders WHERE status = 1 AND city = 'shanghai';
优化器靠索引统计信息估行数,统计信息是采样得来的,数据分布突变或者大批量导入后就会失真。估算偏差几个数量级时,连接顺序和索引选择都会跟着选错。这一点先确认清楚,后面就不用反复试。
「explain 行数估算」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
备份不是备了就行,恢复一次才算数,很多备份文件打开才发现是空的。
具体做法是,先看 innodb_stats_persistent 是否为 ON 统计信息有没有持久化;对表执行 analyze table 重新采样 再跑一次 explain;采样页数太少就把 innodb_stats_persistent_sample_pages 调大;数据每天大批量变化的表 把统计更新放进定时任务。
改完照着核一遍,explain 的 rows 和实际扫描行数落在同一个量级 耗时回到 30 毫秒附近。
