SQL标量子查询是指出现在SELECT列表、WHERE条件或HAVING子句中,且保证只返回一行一列结果的子查询。它常用于取关联表的某个聚合值或最新记录,但在一些场景下并不适合使用,甚至会给系统带来明显负担。

一、什么是标量子查询
标量子查询最常见的写法是放在SELECT后面,例如下面的语句根据员工ID取部门名称:
SELECT e.id, e.name, (SELECT d.dept_name FROM department d WHERE d.id = e.dept_id) AS dept_name FROM employee e;
这里子查询依赖外部e.dept_id,对employee每一行都会执行一次,属于关联标量子查询。
二、应避免使用的场景
1. 外部结果集很大且子查询无索引
如果employee表有百万行,而department.id上没有索引,那么上述语句会执行百万次全表扫描,响应时间会非常长。
2. 子查询可能返回多行
标量子查询严格要求最多一行。若关联条件写错导致返回多行,数据库会直接报错,例如:
-- 假设一个部门有多个重名记录,下面会报单行子查询返回多行 SELECT e.name, (SELECT d.dept_name FROM department d WHERE d.code = e.code) FROM employee e;
3. 可以用JOIN替代的聚合取值
当只是取关联表的一对一属性,使用LEFT JOIN通常比标量子查询更易让优化器选择好计划:
SELECT e.id, e.name, d.dept_name FROM employee e LEFT JOIN department d ON d.id = e.dept_id;
4. 写在WHERE中导致无法使用索引
某些数据库对标量子查询在过滤条件中的谓词推入支持有限,可能造成全表扫描。
三、使用边界总结
| 场景 | 是否建议使用标量子查询 |
|---|---|
| 小表且一对一关联 | 可以 |
| 大表无索引关联 | 避免 |
| 需要取聚合值且可JOIN | 优先JOIN |
| 结果可能多行 | 禁止 |
四、如何判断是否为性能瓶颈
可以通过执行计划查看是否出现FILTER操作或多次重复访问表。若发现标量子查询被反复执行,应改写为JOIN或先物化临时表。
标量子查询是工具而非万能写法,清楚它的边界才能写出可维护的SQL。
在写SQL时,先估算外部行数和关联字段索引情况,再决定是否使用标量子查询,可以避免很多线上慢查询问题。