哪个SQL语句更快?(HAVING vs. WHERE...)

53
SELECT NR_DZIALU, COUNT (NR_DZIALU) AS LICZ_PRAC_DZIALU
    FROM  PRACOWNICY
    GROUP BY NR_DZIALU
    HAVING NR_DZIALU = 30
或者
SELECT NR_DZIALU, COUNT (NR_DZIALU) AS LICZ_PRAC_DZIALU
    FROM PRACOWNICY
    WHERE NR_DZIALU = 30
    GROUP BY NR_DZIALU

我已经整理了关于HAVING子句的优化技巧,供有需要的人对查询进行优化。详情请参见 https://junaidtechblog.wordpress.com/2019/09/04/optimize-sql-query-groupby-having/。 - Junaid Ali
8个回答

87

理论上(我指的是SQL标准),WHERE在返回行之前限制结果集,而HAVING在获取所有行后再限制结果集。因此,WHERE更快。在这方面符合SQL标准的DBMS中,只有当无法在WHERE子句中设置条件时(例如在某些RDBMS中的计算列中),才使用HAVING。

您可以查看两者的执行计划并自行检查,没有什么能胜过这种方式(使用您特定环境中的数据和查询进行测量)。


2
我说执行计划,可以看到数据库获取数据的步骤。150行太少,无法注意到执行时间上的任何差异,但如果计划不同,则在具有更多行数的表上会有所影响。在运行查询之前使用“set showplan on”... - Vinko Vrsalovic
1
就此而言,在 MS SQL Server 2005 中,执行计划是相同的。 - Sören Kuklau
这不取决于表和子集的大小,以及整个表中where语句的成本与针对子集的where语句的成本之间的比较吗? - JoeBrockhaus
这句话存在一些基本的误解。SQL标准规定了语句在输入方面返回的内容,但并未涉及性能问题。 - philipxy
@philipxy 当然,它并没有直接涉及性能问题,但它确实说明了语句的作用:在这种情况下,“从前一个子句的结果中消除组”,因此在一般情况下不太可能更快。当然,在特定条件下的具体实现和优化可以使其同样快,这就是为什么查看计划是答案的重要部分。 - Vinko Vrsalovic
显示剩余2条评论

11
可能会根据不同的数据库引擎而异。例如,MySQL几乎是在处理完所有操作之后才应用HAVING子句,这意味着优化的空间几乎没有。从手册中可知:

HAVING子句几乎是在最后应用的,在向客户端发送项之前,不进行任何优化。(LIMIT在HAVING之后应用。)

我相信大多数 SQL 数据库引擎都是以此方式运行,但不能保证。


1
呵呵,"这取决于引擎,但我相信它们都会表现得像这样" :-) - Vinko Vrsalovic
6
好的,我只能谈论我所知道的并对其余部分进行推测 :) - Eran Galperin

8

这两个查询是等价的,您的数据库管理系统查询优化器应该能够识别并生成相同的查询计划。虽然可能不会,但情况相当简单易懂,所以我期望任何现代系统(甚至Sybase)都可以处理。

HAVING子句应该用于对组函数应用条件,否则它们可以移动到WHERE条件中。例如,如果您想将查询限制为具有COUNT(DZIALU)> 10的组,那么您需要将条件放入HAVING中,因为它作用于组而不是单个行。


3
"

WHERE"比"HAVING"更快!

查询的分组越复杂,使用"HAVING"进行比较的速度就会变慢,因为:"HAVING"将处理更多的结果,并且还需要额外的"过滤"循环。

"HAVING"也会使用更多的内存(RAM)。

尽管在处理小数据时,差异很小,可以完全忽略不计。

"

2

我认为使用WHERE子句会更快,但是他们可能会进行优化以达到相同的效果。


2
说优化并不是真正控制并告诉计算机该做什么。我同意使用having不是where子句的替代品。Having有一个特殊的用法,被应用于通过类似sum()的东西分组的地方,并且您想将结果集限制为仅显示具有sum() > 100的组等等。Having适用于组,Where适用于行。它们是不同的事物。因此,它们不应该被比较,因为它们是两个非常不同的实体。

2

与大量数据相比,“Having”较慢,因为它针对记录组进行操作,而“WHERE”则针对行数进行操作。

“Where”在带来所有行之前限制结果,“Having”在带来所有行之后限制结果。


0

这两个语句的性能将是相同的,因为SQL Server足够智能,可以将这两个相同的语句解析成类似的计划。

因此,在查询中使用WHERE或HAVING并不重要。

但是,从语法上讲,理想情况下应该使用WHERE子句。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接