SIMPLE 表示最基础的查询类型,即无子查询、无 UNION、无派生表;即使含 JOIN、WHERE、ORDER BY 或 LIMIT,只要所有表平铺于 FROM 子句且无嵌套,select_type 仍为 SIMPLE。

select_type 为 SIMPLE 时代表什么
表示这是最基础的查询类型:没有子查询、没有 UNION、也没有派生表。哪怕用了 JOIN,只要没嵌套,select_type 仍是 SIMPLE。
常见误判是以为多表 JOIN 就不是 SIMPLE —— 实际上只要所有表都在 FROM 子句里平铺出现,优化器就把它归为 SIMPLE。
-
EXPLAIN SELECT * FROM users JOIN orders ON users.id = orders.user_id;→select_type: SIMPLE - 哪怕加了
WHERE、ORDER BY、LIMIT,只要没子查询,仍是SIMPLE - 注意:如果
JOIN中某张表是子查询结果(比如(SELECT ...) AS t),那它就不再是SIMPLE,而会变成DERIVED
PRIMARY 和 SUBQUERY 的区分关键在嵌套层级
PRIMARY 不是“主键查询”,而是“最外层那个 SELECT”;SUBQUERY 是指出现在 SELECT 列表或 WHERE 子句中、但**不在 FROM 里**的子查询。
典型陷阱:写 SELECT (SELECT name FROM dept WHERE id = emp.dept_id) FROM emp,外层是 PRIMARY,括号里那个就是 SUBQUERY —— 它只执行一次(不依赖外部行),但如果改成 WHERE id = (SELECT ...) 且子查询引用了外层字段,就升级为 DEPENDENT SUBQUERY。
-
SELECT *, (SELECT COUNT(*) FROM logs l WHERE l.user_id = u.id) cnt FROM users u→ 外层PRIMARY,子查询是SUBQUERY -
SELECT * FROM users WHERE id IN (SELECT user_id FROM active_sessions)→ 若子查询无外部引用,仍是SUBQUERY;若写成... WHERE id IN (SELECT user_id FROM active_sessions WHERE user_id = users.id),就变成DEPENDENT SUBQUERY -
DEPENDENT SUBQUERY每次都要重执行,性能风险极高,应优先考虑改写为JOIN
DERIVED 出现在 FROM 子句中的子查询
只要你在 FROM 后面跟了个括号子查询,MySQL 就必须先执行它、生成临时表,再对外层查询生效——这个临时表在 EXPLAIN 的 table 列显示为 ,对应行的 select_type 就是 DERIVED。
容易忽略的是:即使子查询本身很简单(比如 SELECT id FROM t WHERE status=1),只要它被放在 FROM 里,就会触发物化(materialization),产生额外 I/O 和内存开销。
-
SELECT * FROM (SELECT id, name FROM users WHERE city='Beijing') u WHERE u.name LIKE 'A%'→ 内层是DERIVED,外层是PRIMARY - MySQL 5.7+ 可能自动将简单
DERIVED提升为UNCACHEABLE SUBQUERY或跳过物化,但不可依赖;8.0 默认仍物化 - 如果子查询结果集大,
DERIVED很可能成为瓶颈;可尝试用CTE(MySQL 8.0+)替代,或拆成临时表手动控制
UNION 和 UNION RESULT 的执行顺序与 ID 关系
UNION 查询中,第一个 SELECT 是 PRIMARY,第二个起都是 UNION;最终合并结果的那行,select_type 是 UNION RESULT,且它的 id 总是 NULL。
关键点在于:id 值越大越先执行 —— 所以 UNION 的子查询(id=2,3...)比外层 PRIMARY(id=1)更早跑完,但它们的结果要等 UNION RESULT 这一步才真正组装输出。
-
SELECT id FROM t1 UNION SELECT id FROM t2→ 第一行id=1, select_type=PRIMARY;第二行id=2, select_type=UNION;第三行id=NULL, select_type=UNION RESULT - 如果
UNION里某个子查询又含子查询(比如SELECT (SELECT ...) FROM t1),那嵌套部分可能是DEPENDENT SUBQUERY,而它所属的那条UNION行仍是UNION类型 -
UNION RESULT不访问任何表,type列固定为ALL,但不用怕——它只是归并动作,不扫数据
实际看执行计划时,select_type 最容易被当成标签忽略,但它直接暴露了查询结构是否合理:一个本该用 JOIN 实现的逻辑,如果被写成 DEPENDENT SUBQUERY 或层层 DERIVED,性能往往已经掉坑里了。











