type为all说明全表扫描,索引未生效;主因是join字段类型不一致或where中对字段用函数导致隐式转换或索引失效,应统一类型、避免函数操作字段。

直接看执行计划,type 是 ALL 或 rows 过大,基本就是索引没用上或 JOIN 顺序错了——优化得从这两处下手,其他都是锦上添花。
EXPLAIN 看出 type=ALL 怎么办
这说明某张表正在全表扫描,根本没走索引。常见原因不是没建索引,而是索引建得不对或被写法绕过了。
-
JOIN字段类型不一致(比如users.id是BIGINT,orders.user_id是INT),会导致隐式转换,索引失效 -
WHERE条件里对字段用了函数,比如WHERE DATE(create_time) = '2026-08-01',必须改成WHERE create_time >= '2026-08-01' AND create_time - 复合索引字段顺序错:比如查询是
WHERE status = 'paid' AND user_id = 123 ORDER BY created_at,索引就得是(status, user_id, created_at),而不是反过来 -
EXPLAIN中key列为NULL,但possible_keys有值?检查是否用了OR、!=或IS NULL等容易让优化器放弃索引的写法
多表 JOIN 后 rows 爆涨怎么调
MySQL 的 rows 是预估中间结果集大小,不是最终返回行数。它暴涨,往往是因为驱动表选错了,或者 LEFT JOIN 强制了低效顺序。
-
LEFT JOIN左边一定是驱动表,哪怕左边是千万级订单表、右边只是百行状态字典表,也会先扫光左边——能改INNER JOIN就别硬用LEFT JOIN - 把过滤性最强的表放最前面:比如
WHERE users.status = 'active'能筛掉 95% 用户,那就该让users当驱动表,而不是先关联orders - 用
STRAIGHT_JOIN强制顺序,但只在EXPLAIN确认优化器选错且你清楚数据分布时才加,否则可能适得其反 - 避免
SELECT *:如果只查users.id, orders.amount,就建覆盖索引INDEX (status, id)和INDEX (user_id, amount),让Extra出现Using index
为什么加了索引还是慢,Extra 里总带 Using temporary
这说明 MySQL 不得不建临时表来完成排序或去重,通常因为 ORDER BY / GROUP BY 字段没走索引,或 JOIN 后字段不在同一张表的索引里。
-
ORDER BY a, b要走索引,索引必须是(a, b)或更长前缀;如果写成ORDER BY b, a,即使有(a, b)索引也用不上 -
GROUP BY后跟聚合函数,且涉及多表字段时,很难避免临时表——优先考虑程序层分组,或提前在中间表里物化好聚合结果 -
DISTINCT在多表 JOIN 后出现,等价于隐式GROUP BY,一样触发临时表;若只需去重 ID,可先SELECT DISTINCT user_id FROM ...再关联 -
UNION比OR更易走索引,但要注意UNION ALL不去重,性能更好;真要UNION,确保每个子查询都能独立走索引
真正卡住性能的,往往不是“要不要加索引”,而是“索引字段顺序是否匹配查询模式”和“JOIN 表顺序是否放大了中间结果集”——这两个点一旦错,加再多索引也没用。











