好、坏或无所谓:哪里 1=1

Wer*_*rCD 16 performance optimization

鉴于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
Run Code Online (Sandbox Code Playgroud)

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

鉴于我不想“过早优化” - 我确实想遵循良好的做法。我以前看过查询计划,但通常只是为了找出我可以添加(或调整)哪些索引以使我的查询运行得更快。

那么问题真的……会Where 1=1导致不好的事情发生吗?如果是这样,我怎么知道?

次要编辑:我也一直“假设”1=1会被优化,或者在最坏的情况下可以忽略不计。质疑一句口头禅永远不会有什么坏处,比如“Goto's are Evil”或“过早优化......”或其他假设的事实。不确定是否1=1 AND会实际影响查询计划。在子查询中呢?CTE的?手续?

除非需要,否则我不是要优化的人……但如果我正在做一些实际上“不好”的事情,我想尽量减少影响或在适用的情况下进行更改。

spa*_*dba 15

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

有关更多信息,请参阅基数估计期间的常量折叠和表达式评估


Mar*_*ith 10

添加冗余谓词可以使 SQL Server 有所不同。

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

在此处输入图片说明

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

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

不过,简单的参数化通常不是您应该依赖的东西。显式参数化您的查询要好得多。


fil*_*rem 5

在任何现代 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.
Run Code Online (Sandbox Code Playgroud)

对我来说,在 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
Run Code Online (Sandbox Code Playgroud)