直接回答:标准动作是 EXPLAIN (ANALYZE, BUFFERS) 拿真实执行计划,按这几个信号排查:扫描方式——大表出现 Seq Scan 且过滤条件强选择性,多半缺索引;估计偏差——rows 估计与实际差几个数量级,说明统计信息过期或谓词关联性打破假设,后续节点全会被带歪;排序/聚合 spill 磁盘(Sort Method: external merge)说明 work_mem 不够;连接方式——Nested Loop 带大外表是灾难信号;Buffers 命中/读取比揭示是否全在走磁盘。

展开解析:方法论是自底向上读计划:缩进最深的节点最先执行,顺着行数的变化找"哪里行数爆了"。常见根因映射:估计偏差→ANALYZE 更新统计、必要时提高 statistics target 或建扩展统计(多列相关);隐式类型转换导致索引失效(字符串列用数字查)→对齐类型;函数包裹列(WHERE date(created_at)=...)→改写为范围条件或建表达式索引;OR 跨列→改 UNION ALL;大 IN 列表→改临时表 join。MySQL 侧对应看 type(const/ref/range/index/ALL 由好到差)、Extra 里的 Using filesort/temporary。改完务必 ANALYZE 复测真实耗时,并考虑不同数据量下计划是否翻转——优化器的选择随数据分布漂移。

追问方向:为什么优化器有时放着索引不用?join 顺序由什么决定?慢查询日志与执行计划如何配合?

(约 460 字)