我注意到SQL Server(在這種情況下,SQL Server 2008)如何處理select語句內的相關子查詢時有點意外。我的假設是查詢計劃不應該受到在select語句的投影子句中寫入子查詢(或列,就此而言)的順序的影響。但是,這似乎並非如此。投影中相關子查詢排序的影響
考慮以下兩個查詢,這是除子查詢的CTE內的順序相同:
--query 1: subquery for Color is second
WITH vw AS
(
SELECT p.[ID],
(SELECT TOP(1) [FirstName] FROM [Preference] WHERE p.ID = ID AND [FirstName] IS NOT NULL ORDER BY [LastModified] DESC) [FirstName],
(SELECT TOP(1) [Color] FROM [Preference] WHERE p.ID = ID AND [Color] IS NOT NULL ORDER BY [LastModified] DESC) [Color]
FROM Person p
)
SELECT ID, Color, FirstName
FROM vw
WHERE Color = 'Gray';
--query 2: subquery for Color is first
WITH vw AS
(
SELECT p.[ID],
(SELECT TOP(1) [Color] FROM [Preference] WHERE p.ID = ID AND [Color] IS NOT NULL ORDER BY [LastModified] DESC) [Color],
(SELECT TOP(1) [FirstName] FROM [Preference] WHERE p.ID = ID AND [FirstName] IS NOT NULL ORDER BY [LastModified] DESC) [FirstName]
FROM Person p
)
SELECT ID, Color, FirstName
FROM vw
WHERE Color = 'Gray';
如果你看看這兩個查詢計劃,你會看到一個外連接使用對於每個子查詢,並且聯接的順序與子查詢寫入的順序相同。有一個過濾器應用於顏色的外部連接的結果,以濾除顏色不是「灰色」的行。 (對我來說,SQL會使用顏色子查詢的外部聯接,因爲我對顏色子查詢的結果有一個非空限制,但確定。)
大部分行都被顏色過濾器。結果是查詢2比查詢1便宜得多,因爲第二次連接涉及的行較少。拋開這種陳述的所有原因是否是預期的行爲?無論SQL查詢計劃中SQL Server是否選擇儘早移動篩選器,而不管子查詢的寫入順序如何?
編輯:只是爲了澄清,我有一個正在探索這種情況的正當理由。我可能需要創建一個涉及類似構造的子查詢的視圖,現在很明顯,基於從視圖中投影出來的這些列的任何過濾都會因爲列的排序而在性能上發生變化!
和你爲什麼要使用相關子查詢在所有?爲什麼不使用連接? – HLGEM 2010-03-30 21:26:24
如果您爲每個子查詢使用兩個CTE表而不是一個子查詢,那麼查詢計劃的外觀如何。 – Thomas 2010-03-30 21:33:04
@HLGEM我通常會使用一個連接,但在這個例子中,我只關心另一個表中最高的1(或0)值,其中可能有很多。 – 2010-03-30 21:36:21