任何類似於 where 1=0 的 SQL where 子句性能
(我使用的是 SQL Server 2008R2 或更高版本)
為了集中管理和一致,有一個視圖定義如下:
CREATE VIEW view_all_situation ( select null as src, tf.col1, sum(col2) as fee, sum(isnull(v1.col1, 0)) as fee1 ... from table_fee tf inner join parameter_table pt on tf.id = pt.id left join view1 v1 on ... left join view2 v2 on ... where pt.col1 = 0 group by tf.col1 UNION ALL select tfd.src, tfd.col1, sum(col2) as fee, sum(isnull(v1.col1, 0)) as fee1 ... from table_fee_detail tfd inner join parameter_table pt on tfd.id = pt.id left join view1 v1 on ... left join view2 v2 on ... where pt.col1 = 1 group by tfd.col1 ) (Note: parameter_table only have 1 row)
因此,如果 parameter_table.col1 = 1 中的值則返回 table_fee_detail 否則返回 table_fee。(注:parameter_table 只有 1 行)
由於第一部分需要 10 秒,第二部分需要另外 10 秒,最後返回需要 20 秒。如果有更快的方法讓 SQL Server 根據 parameter_table 值執行 UNION ALL 的任一部分,以便它在 10 秒內返回?
由於動態 SQL 不適用於我的情況,我無法建構它來獲得結果。
我試過用
where EXISTS (select 1 from parameter_table where col1 = 0) and where EXISTS (select 1 from parameter_table where col1 = 1)
作為 where 子句,它不能使 SQL Server 在 10 秒內返回。它仍然使用 20 秒。
是否有可能有類似結果的 SQL
where 1=0
以便 SQL Server 在 10 秒內返回結果?
For example, if parameter_table.col1 = 0, i get result from table_fee Src col1 fee fee1 -------------------------------------------- null USD 100 150 null EUR 200 150 null AUD 300 200 if parameter_table.col1 = 1, I get result from table_fee_detail Src col1 fee fee1 -------------------------------------------- USA USD 100 150 GER EUR 200 150 AU AUD 300 200
您正在尋找動態地從兩個表之一中選擇行。這通常可以在沒有動態 SQL 的情況下實現。
為了展示,這裡是一個基於AdventureWorks 範例數據庫的簡化版本:
這個想法是根據Parameter表中**UseArchive列的值從每個Product的**TransactionHistory或TransactionHistoryArchive表中選擇行:
CREATE TABLE dbo.Parameter ( ProductID integer NOT NULL PRIMARY KEY, UseArchive bit NOT NULL ); INSERT dbo.Parameter (ProductID, UseArchive) VALUES (1, 0), (2, 0), (3, 1), (4, 0);
此範例指定產品 1、2 和 4 的行應來自 TransactionHistory。對於產品 3,行應來自**TransactionHistoryArchive。
解決方案:
SELECT P.Name, CA.TransactionID FROM Production.Product AS P JOIN dbo.Parameter AS PTR ON PTR.ProductID = P.ProductID CROSS APPLY ( SELECT TH.ProductID, TH.TransactionID FROM Production.TransactionHistory AS TH WHERE TH.ProductID = P.ProductID AND PTR.UseArchive = 0 UNION ALL SELECT THA.ProductID, THA.TransactionID FROM Production.TransactionHistoryArchive AS THA WHERE THA.ProductID = P.ProductID AND PTR.UseArchive = 1 ) AS CA;
此查詢的執行計劃是:
這裡的關鍵是應用內部的外部引用
PTR.UseArchive = value
。這允許優化器建構一個具有啟動表達式的過濾器的計劃。例如,TransactionHistory表 Index Seek 上方的 Filter 有:當然,另一個 seek 上方的 Filter Predicate 非常相似,但會測試UseArchive = 1。
每個過濾謂詞對每個產品進行一次評估。它確定計劃中它下面的查找是否將在嵌套循環連接的迭代中執行。
在這個例子中,效果是TransactionHistory index seek執行了3次;TransactionHistoryArchive表上的查找只執行一次。
您可能能夠為您的案例實現此模式。
刪除 4 個左連接。您沒有使用他們的數據,也不需要他們。它會減慢一切,特別是如果您沒有正確的 PK 和索引(告訴我們更多資訊)
parameter_table.id 應該是一個 PK 和/或上面有 1 個或 2 個索引,例如(它實際上取決於您的模型):
create index idx_parameter_table_id0 on parameter_table(id) where col1 = 0 create index idx_parameter_table_id1 on parameter_table(id) where col1 = 1
要麼
create index idx_parameter_table_id1 on parameter_table(col1, id)
如果 col2 來自 parameter_table,則將其包含在索引中可能會很有用:
create index ... on parameter_table(...) include (col2)