SQL 问题:WHERE 子句的顺序有区别吗?

Posted

技术标签:

【中文标题】SQL 问题:WHERE 子句的顺序有区别吗?【英文标题】:SQL question: Does the order of the WHERE clause make a difference? 【发布时间】:2009-09-22 04:10:18 【问题描述】:

从性能的角度来看,我的 SQL WHERE 语句的顺序有影响吗?

例如

SELECT ... FROM ...
WHERE a > 1
AND b < 2

会比这个更快/更慢

SELECT ... FROM ...
WHERE b < 2
AND a > 1

我们还假设我事先知道a &gt; 1 会最大程度地缩小结果集。

另外,如果我按照 WHERE 语句的顺序连接两个或多个表,这有关系吗?

【问题讨论】:

阅读此sql-server-performance.com/tips/t_sql_where_p1.aspx。 与***.com/questions/642784/…相关(也可能是其所为) SQL - Does the order of WHERE conditions matter?的可能重复 这能回答你的问题吗? Does the order of columns in a WHERE clause matter? 【参考方案1】:

理论上没有区别。

有时,特别是对于更简单的优化器,查询计划会根据 WHERE 子句中子句的顺序而有所不同。有一个中等强度的论点认为这种差异是错误的征兆。

类似的 cmets 也适用于加入订单。连接的顺序应该无关紧要 - 对于相同类型的连接。显然,表 Table2 是内连接还是外连接到另一个表 Table1 确实很重要 - 无论是 Table1 LEFT JOIN Table2Table1 RIGHT JOIN Table2 还是 Table1 FULL JOIN Table2,这都很重要。但是对于一系列 INNER JOIN 操作,顺序应该无关紧要。如果您正在处理连接链,则在某种程度上可能会强制处理顺序。

澄清(再次) - 考虑:

(Table1 AS t1 JOIN Table2 AS t2 ON t1.pkcol = t2.fkcol) AS j1
JOIN
(Table3 AS t3 JOIN Table4 AS t4 ON t3.pkcol = t4.fkcol) AS j2
ON j1.somecol = j2.anothercol

它的编写方式,显然程序员希望 (t1, t2) 和 (t3, t4) 上的连接在 (j1, j2) 上的连接之前执行,但优化器可能能够执行连接不同。例如,如果 j1.somecol 派生自 Table1 而 j2.anothercol 派生自 Table4,则优化器可能能够选择 Table1.SomeCol = Table4.AnotherCol 上的联接而不是其他任何联接。此类问题可能会受到 WHERE 子句中的过滤条件以及各种表上是否存在适当索引的影响。这就是统计数据在优化器生成查询计划的方式中发挥重要作用的地方。

【讨论】:

+1 了解详细信息,在一两段中解释查询优化是一项艰巨的任务。 不是不同意,只是分享一个不寻常的例子......我们遇到了一个场景,如果我们将它作为第一个包含在 SQL 2000 中使用的第三方加密例程将严重影响查询的性能where 子句中的表达式,而不是最后一个表达式。首先,对表中的整个记录​​集应用解密。最后,对表中较小的记录子集应用解密。有问题的查询从过度(30 秒、3 分钟等)变为可接受(1-2 秒)。 @Mayo:有趣的例子...理想情况下,“你”(第 3 方加密例程的提供者)有一种方法可以告诉优化器“这个函数需要花费一个手臂和一个腿;必要时调用,但在你知道有必要之前不要调用'。如果如我所料,优化器只是假设“它是一个函数;它的成本与 LENGTH() 或其他函数一样多”,那么它可能会对序列做出错误的判断。您强调的是,如果基于成本的优化器对某物的成本没有很好的了解,它有时会做出糟糕的决定。谢谢!【参考方案2】:

不,它没有。大多数现代 SQL 服务器都包含一个查询优化器,它研究所有合理 (*) 解决查询的方法,旧服务器可能会根据 SELECT 子句中的顺序获取提示,而新服务器则不会。

另一方面,JOIN 的顺序在更大程度上仍然很重要。

编辑:请参阅 Jonathan 的 Leffler 的回复,因为他提供了额外的详细信息,特别是关于 JOIN 的顺序。谢谢你,乔纳森!

编辑: ( * ) 合理与可能: 正如 Erikkalen 所指出的,优化器不会调查 所有 em>可能的方式,由于其逻辑中编码的[相当好]启发式,它只会根据它为基础索引保留的统计信息评估合理计划。对于每个计划,它都考虑估计总成本(或部分估计,当部分成本很容易超过另一个计划的总成本[修剪]时),这就是最终选择有效使用的计划的方式。虽然 SQL 查询优化器使用的一般原则众所周知,但其实现的复杂性引入了许多不同的曲折。

【讨论】:

连接的顺序应该无关紧要 - 对于相同类型的连接。显然,表 Table2 是内连接还是外连接到另一个表 Table1 确实很重要 - 无论是 Table1 LEFT JOIN Table2 还是 Table2 LEFT JOIN Table1,这都很重要。但是对于 INNER JOIN,排序应该无关紧要。例如,如果您正在处理星形连接,则在某种程度上可能会强制处理顺序。 @jonathan,你能再说一遍吗……你有点迷失了我(但听起来很有趣) 查看我的答案中添加的材料:D @PirateApp 注意!不同类型的连接可以产生完全不同的结果(更多/更少的行和不同的列带有 NULL 等)。最初的问题是关于性能。现在,如果在更改表的顺序时选择备用连接说明符以获得相同的逻辑查询(因此结果相同),性能通常应该相似。然而 - 再次 - JOIN 的顺序和类型往往更容易影响查询优化器的行为,因此 SQL 实现和/或不同数据集之间的性能一致性可能会有所不同。, @PirateApp 如果 A 和 B 具有相同的连接键集(即“A 中的所有行都在 B 中找到”,如您所写并且找到 B 中的所有行在 A) 中,是的,内部、左和右连接在逻辑上是相同的,在大多数现代 SQL 实现中,使用的特定连接类型不应显着影响性能。我的回答是合格的“是”:通常/一般......连接类型不应影响性能。魔鬼在细节中:使用的 DBMS 和底层数据上下文(例如,最新的索引统计信息?哪些索引可用?表的相对大小?...)【参考方案3】:

见下文并点击链接(长文但值得一读):

SQL Server Transact-SQL WHERE

如果 WHERE 子句包含多个 表达式,一般没有 通过订购获得的性能优势 各种表达方式 特定的顺序。这是因为 SQL Server 查询优化器执行此操作 为你,为你省力。那里 有几个例外,其中 在本网站上进行了讨论。 [7.0, 2000, 2005] 添加 1-24-2006

【讨论】:

【参考方案4】:

这取决于 DBMS。 SQL 本身并没有说明查询应该如何执行。看具体实现。

如果您的 DBMS 具有按顺序解释查询的非常简单的模型,那么在您的示例中首先放置 > 1 会(显然)更快 - 因为 DBMS 会进行两次传递,其中第二次传递要小得多结果集。

【讨论】:

【参考方案5】:

没有。优化器根据当前统计信息决定过滤结果的顺序。

【讨论】:

即使我知道一个子句会比另一个子句更大幅度地减少/过滤结果集,这是真的吗?意思是,如果我知道“a > 1”会比“b 否 - 如果您知道,优化器也应该这样做,并且可能会首先使用更具选择性的条件。要看是否有索引帮助,a和b是否在同一张表,...【参考方案6】:

如果它来自同一个表,并且查询与您的示例一样简单,那么它没有任何区别。随着您变得越来越复杂并链接更多表,它可以。

【讨论】:

那么,按照顺序,应该先出现什么?过滤器比 WHERE 子句的顺序缩小结果集的范围最大 - 第一个 ... 还是最后一个?

以上是关于SQL 问题:WHERE 子句的顺序有区别吗?的主要内容,如果未能解决你的问题,请参考以下文章

SQL Where 子句顺序

where 子句和使用关联对象来提高性能之间有啥区别吗

在SQL语句中同时包含where子句,groupby子句,having子句及聚集函数,将按照怎么样的顺序执行?

WHERE 子句中的字段顺序会影响 MySQL 的性能吗?

SQL中WHERE 和HAVING的区别

Sql 的 Where 子句 - 它可以读取过时的数据吗?