T-SQL 1 = 1性能命中

时间:2009-06-26 14:42:02

标签: sql-server tsql

对于我的SQL查询,我通常对SELECT语句执行以下操作:

SELECT ...
FROM table t
WHERE 1=1
  AND t.[column1] = @param1
  AND t.[column2] = @param2

如果我需要添加/删除/注释任何WHERE子句,这将很容易,因为我不必关心第一行。

使用此模式时是否有任何性能损失?

其他信息:

绵羊模拟器和所有其他没有使用的实例。

假设上面的查询,我需要将@param1更改为不包含在查询中:

1 = 1:

...
WHERE 1=1 <-- no change
  --AND t.[column1] = @param1 <-- changed
  AND t.[column2] = @param2 <-- no change
...

没有1 = 1:

...
WHERE <-- no change
  --t.[column1] = @param1 <-- changed
  {AND removed} t.[column2] = @param2 <-- changed
...

8 个答案:

答案 0 :(得分:17)

不,SQL Server足够聪明,可以从执行计划中省略这个条件,因为它总是TRUE

Oracle,MySQL和PostgreSQL也是如此。

答案 1 :(得分:11)

如果您使用分析器并且看起来很可能,您最终会看到优化器最终会忽略它,因此在宏观方案中,可能不会有太多内容。绩效收益或损失的方式。

答案 2 :(得分:3)

这没有性能影响,但SQL文本看起来像是被SQL注入攻击所破坏。在许多基于sql注入的攻击中出现'1 = 1'技巧。您只是冒着某些客户有一天会部署一个监控SQL流量的“黑匣子”的风险,您会发现您的应用被标记为“黑客”。源代码分析器也可以标记这一点。当然,这是一个漫长的过程,但值得投入其中。

答案 3 :(得分:2)

没有区别,因为他们评估了常数并进行了优化。我在手工和代码生成的ANDOR列表中同时使用1 = 1和0 = 1,但它没有效果。

答案 4 :(得分:2)

由于条件始终为true,SQL Server将忽略它。您可以通过运行两个查询进行检查,一个查询条件,另一个查询条件没有,并比较两个实际执行计划。

实现易于评论要求的另一种方法是重新构建查询:

SELECT ...
FROM table t
WHERE 
    t.[column1] = @param1 AND
    t.[column2] = @param2 AND
    t.[column3] = @param3

然后,您可以在where条件中添加/删除/注释掉行,它仍然是有效的SQL。

答案 5 :(得分:1)

没有表现受到影响。即使您的WHERE子句加载了大量的比较,这也很小。

最好的情况是,这是一个比特的比较。更糟糕的情况是数字被评估为整数。

答案 6 :(得分:1)

对于任何合理复杂的查询,都没有区别。您可以查看一些执行计划,并比较实际执行成本,并亲眼看看。

答案 7 :(得分:1)

这可能会产生一些潜在的负面影响,AND 1=1将阻止SQL Server的simple parameterisation设施启动。

演示脚本

DBCC FREEPROCCACHE;  /*<-- Don't run on production box!*/

CREATE TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131]
(
X INT, 
Y INT,
PRIMARY KEY (X,Y)
);

GO
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  X = 1
       AND Y = 2;
GO
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  X = 2
       AND Y = 3;
GO   
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  1 = 1
       AND X = 1
       AND Y = 2 
GO   
SELECT *
FROM   [E7ED0174-9820-4B29-BCDF-C999CA319131]
WHERE  1 = 1
       AND X = 2
       AND Y = 3    
SELECT usecounts,
       execution_count,
       size_in_bytes,
       cacheobjtype,
       objtype,
       text,
       creation_time,
       last_execution_time,
       execution_count
FROM   sys.dm_exec_cached_plans a
       INNER JOIN sys.dm_exec_query_stats b
         ON a.plan_handle = b.plan_handle
       CROSS apply sys.dm_exec_sql_text(b.sql_handle) AS sql_text
WHERE  text LIKE '%\[E7ED0174-9820-4B29-BCDF-C999CA319131\]%' ESCAPE '\'
       AND text NOT LIKE '%this_query%'
ORDER BY last_execution_time DESC       

GO

DROP TABLE [E7ED0174-9820-4B29-BCDF-C999CA319131]   

显示缓存计划的单个参数化版本满足不带1=1的查询,而1=1的查询编译并存储不同常量值的单独计划。

enter image description here

理想情况下,您不应该依赖于此,并且应该明确地参数化查询以确保参数化所需的元素并且参数具有正确的数据类型。