MySQL 慢查询日志里 rows_examined 比返回行数大三个数量级,问题出在哪
rows_examined 是优化器实际扫描的行数,返回行数只看结果集大小。两者差三个数量级,说明索引没吃到或者吃错了列,按下面顺序排查。
第一步看 EXPLAIN 的 type 和 key。type 是 ALL 说明全表扫,index 说明扫了整棵索引树同样不划算,只有 range、ref、eq_ref 才算用上。key 为 NULL 就是没走索引,重点查 WHERE 列有没有索引、索引列上有没有套函数或隐式类型转换。最典型的是 varchar 列传了数字,MySQL 会做隐式转换,索引直接失效。
第二步看 rows 和 filtered。rows 是预估扫描行数,filtered 是过滤后剩余百分比。预估很小但实际很慢,多半统计信息过期,跑一次 ANALYZE TABLE 再看。
第三步看回表。二级索引查到主键后要回表取其他列,命中行数一多,优化器会干脆放弃索引走全表扫。覆盖索引能省掉回表,把 SELECT 需要的列一起建进索引通常立竿见影。
第四步看 ORDER BY 和 GROUP BY。和索引顺序不一致时会产生 Using filesort 或 Using temporary,扫描量被放大。联合索引的列顺序要和 ORDER BY 对齐,方向也要一致。
最后提醒一个容易误判的情况:LEFT JOIN 右表没索引,或者子查询被改写成半连接,都会让 rows_examined 暴涨,而单看某张表的 EXPLAIN 看不出问题。用 EXPLAIN FORMAT=JSON 看完整执行计划,或者开 optimizer_trace 看优化器怎么选的路,比猜快得多。
- 点赞
- 收藏
- 关注作者
评论(0)