我們有TABLE A按日期進行分區,並且不包含今天的數據,它只包含前一天的數據,並且還包含年初至今的數據。SQL Server 2005查詢計劃優化器在日期分區表上窒息
我們已經將表B按照包含今天的數據以及從前一天到今年的數據進行分區。上表B的頂部有它連接針對View_C
,View_D
和左外聯接表E. View_C
和View_D
從1個表中的每個選擇和不具有任何其它表連接在一個視圖,View_B
所以View_B
看起來像
SELECT b.Foo, c.cItem, d.dItem, E.eItem
FROM TABLE_B b JOIN View_C c on c.cItem = b.cItem
JOIN View_D d on b.dItem = d.dItem
LEFT OUTER JOIN TABLE_E on b.eItem = e.eItem
View_AB
在提取日期以及另一個約束條件下加入表A和View_B
。所以它看起來是這樣的:
SELECT a.Col_1, b.Col_2, ...
FROM TABLE_A a LEFT OUTER JOIN View_B b
on a.ExtractDate = b.ExtractDate and a.Foo=b.Foo
-- no where clause
當從超過前一天的任何其他數據搜索,查詢分析器做什麼預期和做了哈希匹配連接,完成外連接,並讀取約116頁價值來自表B的數據。然而,如果在前一天運行,查詢優化器會嚇倒並使用嵌套連接,掃描表7000次以上並在連接中讀取8,000,000多頁。
我們可以通過使用聯接提示來僞造/強制它使用不同的查詢計劃,但是會導致視圖中的任何約束都會導致優化器拋出查詢無法處理的錯誤由於加入提示而完成。
編輯以添加pages/scans =與先前運行優化程序正確選擇散列而不是嵌套連接的前一天運行的掃描相同的編號。
正如評論所說,我們嚴厲通過創建TABLE_B
覆蓋索引覆蓋在View_B
的加入降低了衝擊,但IO仍然高於這將是,如果優化器選擇正確的計劃,特別是因爲除了前幾天的搜索之外,該指數基本上是多餘的。
該sqlplan是在http://pastebin.com/m53789da9,抱歉,它不是格式很好的版本。
任何機會,你可以發佈每個.sqlplan,所以我們可以看到差異? – chadhoc 2009-11-17 14:34:25
是由ExtractDate聚集的兩個表嗎? ExtractDate上的非覆蓋非聚集索引也可能導致此行爲(即使使用分區)。 – 2009-11-17 16:08:20
這些表也由ExtractDate聚類,A和B之間的連接標準應該由表上的索引覆蓋。我們通過在連接標準上創建一個覆蓋索引來緩解了這個問題。在最佳連接中,它仍然會執行更多的頁面讀取操作,但這是可以接受的。 – Rebthor 2009-11-18 14:44:16