WHERE子句中列的顺序是否重要?

时间:2009-03-13 13:46:28

标签: sql-server performance

WHERE子句中列的顺序是否会影响性能?

e.g。

假设我首先列出了具有更高潜力的专栏,反之亦然?

7 个答案:

答案 0 :(得分:15)

使用一个不错的查询优化器:它不应该。

但在实践中,我怀疑它可能。

您只能通过测量来判断您的情况。随着数据库中数据分布的变化,测量结果可能会发生变化。

答案 1 :(得分:12)

对于Transact-SQL,WHERE子句的condition中的运算符有一个已定义的优先级。优化器可能会重新排序此评估,因此您不应依赖短路行为来确保正确性。订单通常是从左到右,但索引的选择性/可用性可能也很重要。简化搜索条件应该可以提高优化器处理它的能力。

例如:

 WHERE (a OR b) AND (b OR c)

可以简化为

 WHERE b OR (a AND c)

显然,在这种情况下,如果可以构造查询以查找b是否先占优势,那么它可以跳过a和c的评估,从而运行得更快。优化器是否可以执行这个简单的转换我无法回答(它可能会),但关键是它可能无法进行任意复杂的转换,您可以通过重新排列条件来影响查询性能。如果b更具选择性或具有索引,则优化器可能首先能够使用它构建查询。

编辑:关于基于唯一性的排序问题,我假设您可以根据您对数据的知识(实际的,未假定的)提供给优化程序的任何提示不疼假装它不会进行任何优化并构建您的查询,就好像您需要将其从大多数选择到最不具有选择性,但是在性能实际上是一个问题之前不要对它进行任何考虑。

引自上述参考文献:

  

逻辑运算符的优先顺序不是(最高),   然后是AND,然后是OR。括号可用于覆盖   搜索条件中的此优先级。评估的顺序   逻辑运算符可以根据查询的选择而变化   优化

答案 2 :(得分:8)

对于SQL Server 2000/20005/2008,无论您如何在WHERE子句中排列列,查询优化器通常都会给出相同的结果。话虽如此,在编写数以千计的T-SQL命令的过程中,我发现了一些订单改变了性能的极端情况。以下是似乎受此问题影响的查询的一些特征:

  1. 如果您的查询中有大量表格(10个或更多)。

  2. 如果WHERE子句中有多个EXISTS,IN,NOT EXISTS或NOT IN语句

  3. 如果您使用的是嵌套CTE(公用表表达式)或大量CTE。

  4. 如果您的FROM子句中有大量子查询。

  5. 以下是尝试评估快速解决性能问题的最佳方法的一些提示:

    1. 如果问题与1或2有关,则尝试重新排序WHERE子句并比较估计查询计划中查询的子树成本。

    2. 如果问题与3或4有关,则尝试将子查询和CTE移出查询并让它们加载临时表。如果减少来自T-SQL语句主体的复杂连接和子查询的数量,查询计划优化器在估计查询计划方面更有效率。

    3. 如果您使用的是临时表,请确保已为临时表指定了主键。这意味着避免使用SELECT INTO FROM来生成表。相反,在使用INSERT INTO SELECT语句之前,显式创建表并指定主KEY。

    4. 如果您正在使用临时表,并且服务器上的MANY进程也使用临时表,那么您可能希望创建一个在查询过程中被截断并重新加载的更永久的临时表。如果您使用TempDB存储工作/临时表,则更有可能遇到磁盘争用问题。

    5. 移动WHERE子句中的语句,将多数数据过滤到WHERE子句的开头。请注意,如果这是您解决问题的方法,那么当查询计划再次混淆生成和选择最佳执行计划时,您的性能可能会再次降低。您最好找到一种方法来降低查询的复杂性,以便WHERE子句的顺序不再相关。

    6. 我希望您觉得此信息有用。祝你好运!

答案 3 :(得分:2)

这完全取决于DBMS,查询优化器和规则,但通常会影响性能。

如果对where子句进行了排序,使得第一个条件显着减少了结果集,则只需要针对较小的集合评估剩余条件。遵循该逻辑,您可以根据where子句中的条件顺序优化查询。

答案 4 :(得分:2)

理论上任何两个等效的查询都应该生成相同的查询计划。由于WHERE子句的顺序对查询的逻辑含义没有影响,这应该意味着WHERE子句的顺序应该没有效果。

这是因为查询优化器的工作方式。在大大简化的概述中:

  1. 第一个SQL Server解析查询并构造逻辑运算符树(例如JOINSELECT)。
  2. 然后它将这些逻辑运算符转换为“物理操作树”(例如“嵌套循环”或“索引扫描”,即执行计划)
  3. 接下来,它通过交换等效操作来排列等效的“物理操作树”(即执行计划),估计每个计划的成本,直到找到最佳计划。
  4. 完成第二步是一种完全缓解的方式 - 它只是选择第一个/最明显的物理树,但是在第三步中,查询优化器能够查看所有等价物物理树(即执行计划),因此只要查询实际上是等效的,我们在步骤2中得到的初始计划无关紧要,所有计划在步骤3中考虑的计划集都是相同的。

    (我不记得逻辑/物理树的真实姓名,它们在一本书中,但不幸的是,这本书现在是我世界的另一面)

    有关详细信息,请参阅以下系列博客文章Inside the Optimizer: Constructing a Plan - Part 1

    实际上但是,查询优化器通常没有机会在步骤3中考虑所有等效树(对于复杂查询,可能存在大量可能计划),所以在一定的截止时间后,第3步缩短,查询优化者必须选择迄今为止找到的最佳计划 - 在这种情况下,不会考虑所有计划。 / p>

    为了确保查询优化器有选择地和智能地选择要考虑的计划,还有很多背后的魔术,所以大多数时候计划选择“足够好” - 即使它不是绝对的最快的计划,它可能没有理论上最快的那么慢,

    然而,这意味着如果我们在步骤2中有不同的起始计划(如果我们以不同的方式编写查询,可能会发生这种情况),这可能意味着在步骤3中考虑了不同的计划子集,因此理论上 SQL Server可以针对等效查询提出不同的查询计划,具体取决于它们的编写方式。

    实际上,99%的时间你不会注意到差异(对于许多简单的计划,不会 任何差异,因为优化者实际上会考虑所有计划)。此外,您无法预测其中任何一个是如何工作的,因此可能看似合理的事情(例如将WHERE子句按特定顺序放置)可能没有预期的效果。

答案 5 :(得分:0)

绝大多数案例中,查询优化器将确定选择所请求数据的最有效方式,而不考虑WHERE子句中定义的SARGS的顺序。

排序由诸如所讨论的列的选择性(SQL Server根据统计信息知道)以及是否可以使用索引等因素确定。

答案 6 :(得分:-4)

如果你是ANDing条件,则第一个不为true将返回false,因此顺序会影响性能。