HAVING 从不比 WHERE 性能更好,因为 WHERE 在分组前基于原始行过滤并可利用索引,而 HAVING 必须等待 GROUP BY 完成聚合计算后才执行,无法跳过中间结果。
HAVING 从不比 WHERE 性能更好——这是个常见误解,根源在于混淆了“执行阶段”和“数据量”。
SQL 引擎严格按固定顺序执行:FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY。这意味着:
WHERE 在分组前过滤原始行,能直接利用索引、跳过大量数据,降低后续计算开销HAVING 必须等 GROUP BY 完成、所有聚合值(如 SUM()、COUNT())算出来之后才开始工作,此时数据已分组、内存中存着中间结果集SELECT 1 HAVING 1=1(无 GROUP BY),多数数据库(如 MySQL 5.7+、PostgreSQL)也把它当作单一分组处理,仍绕不开聚合计算流程实际观察到的“HAVING 查询更快”,几乎都源于对比方式错误或隐藏变量干扰:
WHERE 但没建索引的查询(如 WHERE status = 'pending'),跟一个带 HAVING 且恰好命中缓存的查询比——错把缓存效应当性能优势WHERE 写在 GROUP BY 后(语法错误)、或漏写 GROUP BY 导致查询失败,再换成 HAVING 后“能跑了”,就以为是“优化”决定速度的是「在哪一步减少多少数据」:
WHERE order_date >= '2026-01-01' 过滤掉 95% 历史订单 → 分组只算最近数据 → 快HAVING COUNT(*) > 10 筛选客户 → 引擎必须先为每个客户算出完整计数 → 即使最终只留 5% 分组,前面 100% 的聚合计算已做完 → 慢HAVING 是唯一合法路径,此时谈“优于 WHERE”无意义——它们根本不在同一层面上竞争最常被忽略的一点:有些数据库(如 MySQL 8.0)在 HAVING 条件简单且字段有索引时,会尝试下推优化,但这属于引擎内部黑盒行为,不可依赖;而 WHERE 的索引走查是稳定、可预期、可 explain 验证的。