我有一個存儲過程發出類似於下面的查詢(僞tsql)的查詢。SQL Server組合多個表時的執行計劃
將多個ParentIds
作爲參數(csv)傳入,解析並插入表變量@i
。對於每個ParentId
通過,我們查找StorageTable
並將其包含在@i
中。現在,根據StorageTable
列的值,我們需要從適當的表格(Table1
,Table2
或Table3
)提取數據ParentId
。不存在跨多個表重複的機會 - 因此UNION ALL
。
當我檢查實際的執行計劃時,我發現我的大部分成本/子樹成本(超過一半)花在StorageTable
上,甚至沒有作爲輸入提供。
例如,如果我包含StorageTable = 'Table1'
,表2的索引掃描將顯示在執行計劃中的成本很高。
正如我所料,STATISTICS IO
沒有顯示任何對錶2的讀取,但根據實際的執行計劃,數據訪問點看起來很昂貴。
在我看來,如果某個特定的StorageTable不存在,那麼@i
的內部連接將返回一個空的結果集並「短路」任何額外的工作,不是?
什麼是解決方案?
DECLARE @i AS TABLE
(
ParentId INT,
StorageTable VARCHAR(10)
)
INSERT INTO @i...
INSERT INTO @i...
INSERT INTO @i...
SELECT Col1, Col2, Col3
FROM dbo.Table1 AS T1
INNER JOIN (SELECT * FROM @i WHERE StorageTable = 'Table1') AS I
ON T1.ParentId = I.ParentId
<joins>
<where clause>
UNION ALL
SELECT Col1, Col2, Col3
FROM dbo.Table2 AS T2
INNER JOIN (SELECT * FROM @i WHERE StorageTable = 'Table2') AS I
ON T2.ParentId = I.ParentId
<joins>
<where clause>
UNION ALL
SELECT Col1, Col2, Col3
FROM dbo.Table3 AS T3
INNER JOIN (SELECT * FROM @i WHERE StorageTable = 'Table3') AS I
ON T3.ParentId = I.ParentId
<joins>
<where clause>
您的連接也可以寫成:'INNER JOIN @i AS I ON T1.ParentId = I.ParentId AND I.StorageTable ='Table1',因此子查詢不是必需的。 你可以添加執行計劃嗎? – NickyvV
執行計劃中顯示的成本在這種情況下不可靠。即使在實際計劃中,它們也只是估計的成本,因此不一定反映實際的運行時成本。 –
請只發布(實際)計劃。它可以有任何數量的形狀。 – usr