2009-06-26 71 views
17

對於我的SQL查詢,我平時的SELECT語句如下:T-SQL 1 = 1的性能損失

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

這將使它更容易,如果我需要添加/刪除/發表評論任何WHERE子句,因爲我不必關心第一行。

使用此模式時是否有任何性能問題?

附加信息:

舉例sheepsimulator和所有其他誰沒有得到使用。

假設上面的查詢,我需要改變@參數1爲不包括在查詢:

隨着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 
... 
+1

對不起,如果這聽起來有點兒不對勁,但我真的不知道如何將1 = 1加到WHERE子句中可以獲得上述好處;你能否爲我們這些想要學習這種可能的最佳實踐的人們詳細闡述? – 2009-06-26 14:44:31

+0

@sheepsimulator:這是超級簡單的評論和取消任何條件只是通過預先考慮雙破折號( - ) – Quassnoi 2009-06-26 14:48:21

+2

嘿阿德里安,我總是做同樣的事情,它是如此舒適,建立動態查詢... – tekBlues 2009-06-26 14:52:30

回答

11

如果你使用profiler並且看起來很可能會看到優化器最終會忽略這種情況,所以在宏偉的計劃中,可能不會有太多的績效收益或損失。

+1

我同意。 @ Adrian-如果將這兩個查詢合併在一起並打開執行計劃,您可能會發現兩個查詢都是50%。 – RichardOD 2009-06-26 14:45:27

1

沒有性能影響。即使你的WHERE子句加載了大量的比較,這也很小。

最好的情況是它是一點點比較。更糟糕的情況是數字被評估爲整數。

17

不,SQL Server足夠聰明,可以從執行計劃中省略這個條件,因爲它始終是TRUE

對於Oracle,MySQL和PostgreSQL也是如此。

+0

你有這方面的來源嗎?我相信你,我只是把一些東西聯繫起來。 – 2013-06-27 01:28:48

1

對於任何合理的複雜性查詢,不會有任何區別。您可以查看一些執行計劃,並比較實際執行成本,並親自查看。

2

沒有區別,因爲他們評估常量並進行了優化。我在手和代碼生成的ANDOR列表中都使用1 = 1和0 = 1,並且它沒有效果。

3

這沒有任何性能影響,但是SQL文本看起來像被SQL注入攻擊所破壞。 '1 = 1'技巧出現在許多基於sql注入的攻擊中。你只是冒着你的某個客戶有可能部署監控SQL流量的「黑匣子」的風險,並且你會發現你的應用被標記爲「黑客」。源代碼分析器也可能會標記這一點。當然,它是一個很長的鏡頭,但值得投入的平衡點。

2

由於條件始終爲真,SQL Server將忽略它。您可以通過運行兩個查詢來檢查,一個是條件查詢,另一個查詢沒有查詢,並比較兩個實際執行計劃。

的替代來實現你放心評論要求的,就是要調整你的查詢:

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

然後,您可以添加/刪除/在那裏的條件註釋掉線,它仍然是有效的SQL。

0

這方面的一個潛在的輕微的負面影響是,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

理想情況下,你不應該反正靠這雖然並應明確參數化查詢,以確保所需的元素參數設置和參數有正確的數據類型。