2013-07-19 36 views
2

對SQL Server的這種行爲感到好奇。IN語句掛起SQL Server中的SELECT子查詢

這個查詢產生的結果非常快,就像我期望:

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where (View1.AsOfDate IN (NULL, '20130717')) 

不過,我不希望有一個靜態日期在那裏,所以我用一個子查詢代替它。不幸的是,我已經等待這個查詢執行的時間最長爲5分鐘之前,我取消了,所以我不知道它是否確實會得到我的數據我想:

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where (View1.AsOfDate IN (NULL, (SELECT MAX(AsOfDate) FROM dbo.v_View1))) 

我使出聲明一個變量,用上面的子查詢設置它,然後在IN語句中使用它,該語句按預期工作,並且運行速度與原始查詢快一樣。

我知道我做錯了什麼或錯過了什麼(可能兩者) - 它是什麼?我希望在IN語句中有子查詢,或者至少能夠將這個作爲沒有變量的視圖運行。謝謝!

+2

看看執行計劃。 –

回答

4

我懷疑查詢優化器正在做一些非常奇怪的事情,因爲天真的實現涉及兩個掃描v_View1也許優化器未能認識到子查詢SELECT MAX(AsOfDate) ...將是每行相同。我懷疑它可能沒有意識到子查詢與每一行都沒有關聯,因此對於結果集的每一行都運行它。鑑於完整的外連接,大量數據意味着大量不必要的表掃描。

簡單的解決辦法是:

DECLARE @MaxAsOfDate datetime; 
SET @MaxAsOfDate = (SELECT MAX(AsOfDate) FROM dbo.v_View1) 

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where (View1.AsOfDate IN (NULL, @MaxAsOfDate)) 

這將迫使子查詢執行一次,結果存儲在變量,然後利用它來進行下面的查詢。

+0

是的,我一直在存儲過程中而不是在視圖中這樣做(這看起來更正確,因爲視圖設計器沒有變量的視覺支持),但希望我只是遺漏了什麼。哦,好的 - 謝謝! –

2

我相信它會重新計算每個記錄的MAX(AsOfDate)。一個簡單的解決方案是使用WITH子句(也稱爲公用表表達式),它只能在開始時計算。

0

一個簡單的方法來改寫這個,爲了避免這個問題,就是:

where View1.AsOfDate is null or View1.AsOfDate = (SELECT MAX(AsOfDate) FROM dbo.v_View1) 

編輯:

你的問題是該查詢運行多次。你的問題是這個視圖是非常不優化的。你可以通過重新編譯視圖來解決這個問題。在SSMS中將其作爲ALTER陳述進行編寫並執行。自創建視圖以來,基礎表可能已更改。

我想你也可以通過告訴SQL Server不要使用嵌套循環連接(這是你的性能問題的原因)來解決這個問題。您可以通過將option (hash join, merge join)添加到SQL語句的末尾來完成此操作。

+0

謝謝,但這對我來說是同樣的問題 - 目前已經運行了5分鐘。 –

1

我會建議使用最上面的一個,並改變它,所以它不具有對中陳述NULL這麼寫像這樣

SELECT * 
FROM dbo.v_View1 View1 FULL OUTER JOIN 
    dbo.v_View2 View2 ON View1.Portfolio = View2.Portfolio AND 
    View1.AsOfDate = View2.AsOfDate 
where View1.AsOfDate IN ('20130717') AND View1.AsOfDate IS NULL 

也是完全外連接需要的?或者可以使用INNER JOIN?

此外,如果你看看執行計劃和崗位,我將能夠張貼關於如何最好地優化這個查詢,你還會看到什麼點的詳細信息,查詢耗時最長

Picture of execution plan and how to show it

+0

謝謝 - 這不能解決我想在'WHERE'語句中使用動態AsOfDate的問題。我會看看執行計劃,看看有沒有什麼可疑的東西,謝謝你的提示。 –