好,坏或无所谓:WHERE 1 = 1


14

给定有关reddit的问题,我清理了查询以指出问题在查询中的位置。我首先使用逗号WHERE 1=1,并使修改查询更容易,所以我的查询通常以如下方式结束:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

基本上,有人说1 = 1通常是懒惰的并且对性能不利

考虑到我不想“过早优化”,我想遵循好的做法。我之前已经看过查询计划,但通常只是为了找出可以添加(或调整)哪些索引以使查询运行更快。

这个问题真的...确实 Where 1=1会导致坏事发生?如果是的话,我该如何分辨?

次要编辑:我也一直“假设” 1=1会被优化的东西,或者最坏的情况可以忽略不计。质疑诸如“ Goto's are Evil”或“ Premature Optimization ...”或其他假定事实之类的口头禅也毫不费力。不确定是否1=1 AND会切实影响查询计划。子查询呢?CTE的?程序?

我不是要优化的人,除非需要...但是如果我做的事情实际上是“不好的”,我想将影响降到最低或在适用的情况下进行更改。


2
不,不会。除了几微秒​​的时间,优化器可以消除冗余条件。您最好将重点放在日期字面上不要含糊的地方。
ypercubeᵀᴹ

正如@ypercube所说,这没有什么区别。查询优化程序必须是****,这样的事情才能有所不同;)
Philᵀᴹ13年

4
不要相信您在reddit上阅读的所有内容。请。
亚伦·伯特兰

1
@AaronBertrand在我亲身经历之前,我都会带着一粒盐吃所有东西。我仍然会提出一个听起来合理的问题,看看是否有任何道理,尤其是当它影响我的日常工作时。
WernerCD

4
有盐的颗粒,再有就是整个海洋的含盐量倾倒在你的办公室大楼的顶部:P
Philᵀᴹ

Answers:


13

SQL服务器 解析器优化器具有一个称为“恒定折叠”的功能,该功能可消除查询中的重言式。
如果查看执行计划,则在谓词中的任何地方都不会看到该表达式。这意味着出于这种和其他原因,无论如何在编译时都进行常量折叠,并且对查询性能没有影响。

有关更多信息,请参见基数估计期间的恒定折叠和表达评估


它可能已被编译掉,因为这是进行字段串联的已知模式。
jcolebrand

不,因为它是重言式的,所以已被编译掉。在2736 = 2736时,它将以相同的方式工作,这与通常的1 = 1一样。这同样适用于矛盾。在那种情况下,该功能称为“矛盾检测”。
spaghettidba

“已知模式”的哪一部分表示“必须为1 = 1”?
jcolebrand

9

冗余谓词的添加可以在SQL Server中有所作为。

在下面的执行计划中,请注意@1第一个计划与'foo'第二个计划中的文字。

在此处输入图片说明

这表明SQL Server考虑了第一个简单参数化查询,以促进执行计划的重用-但是,通过比较两个常量,可以防止在第二种情况下发生这种情况。

可以在计划缓存Microsoft技术论文的附录A中找到阻止简单参数化(以前称为自动参数化)的条件的列表:

无论如何,简单的参数化通常都不是您应该依赖的东西。最好显式地设置查询参数。


4

在任何现代的RDBMS中(包括Oracle,Microsoft SQL Server和PostgreSQL-我都可以肯定),这不会影响性能。

有人指出,这只会影响查询计划阶段。因此,仅当您运行数千次不返回任何数据的简单查询的迭代时,差异才可见:

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

对我来说,在PostgreSQL 9.0上,只有10000次迭代才可见:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms

0

当您使用数据库参数cursor_sharing时,这对于Oracle可能是“问题”。设置为“ force”时,它将修改所有SQL语句。查询中的所有“常量”都将被绑定变量替换(例如1 =>:SYS_0)。

引入此选项是为了应对一些懒惰的开发人员。另一方面,它也可能损害其他懒惰的开发人员。但是风险不是很高。从11g开始,它具有绑定变量偷看功能。


您能否澄清一下“自11g起具有绑定变量窥视功能”。手段?
ypercubeᵀᴹ

@ypercube“绑定变量窥视”意味着优化器将观察绑定变量的实际值,并使用数据统计信息重新评估并可能重新生成查询执行计划。我怀疑偷看是否会对正在讨论的结构产生任何影响,因为它不依赖于数据统计。
mustaccio 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.