改進大型“WHERE IN”SQL Server 查詢的統計資訊
目前,我正在嘗試執行以下範例查詢:
SELECT [DATA1], [DATA2] FROM TABLE WHERE [DIMENSION0] IN (1, 5, ... (possibly 10s of numbers)) AND [DIMENSION1] IN (5) AND [DIMENSION2] IN (10) AND [DIMENSION3] IN (48) AND [DIMENSION4] IN (1) AND [DIMENSION5] IN (1) AND [DIMENSION6] IN (8) AND [DIMENSION7] IN (1) AND [DIMENSION8] IN (52) AND [DIMENSION9] IN (1, 10, ... (possibly 100s of numbers)) AND [DIMENSION10] IN (1, 235, ... (possibly 1000s of numbers)) AND [DIMENSION11] IN (1)
該表如下所示;
D = 尺寸
[D0] [D1] [D2] [D3] [D4] [D5] [D6] [D7] [D8] [D9] [D10] [D11] [DATA1] [DATA2]
其中包含所有維度的聚集索引,並且可能包含數百萬條記錄。
當我通過 SSMS 執行此查詢時,我得到以下查詢計劃:
在這裡,它大大高估了它正在尋找的記錄數量,我相信這就是它執行如此緩慢的原因。
我已經更新了統計資訊,但這不是問題,所以我留下了查詢的問題。
我還能夠通過使用以下命令強制 SQL 並行執行來提高查詢速度:
OPTION(QUERYTRACEON 8649)
這會產生以下執行計劃:
這更快,但它仍然高估了行數。
我希望有人能夠幫助我理解為什麼這個估計值如此之高,以及我如何才能降低它。
聚集索引定義:
/****** Object: Index [ClusteredIndex-20180726-083210] Script Date: 26/07/2018 09:47:58 ******/ CREATE UNIQUE CLUSTERED INDEX [ClusteredIndex-20180726-083210] ON [dbo].[TABLE] ( [DIMENSION0] ASC, [DIMENSION1] ASC, [DIMENSION2] ASC, [DIMENSION3] ASC, [DIMENSION4] ASC, [DIMENSION5] ASC, [DIMENSION6] ASC, [DIMENSION7] ASC, [DIMENSION8] ASC, [DIMENSION9] ASC, [DIMENSION10] ASC, [DIMENSION11] ASC, ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
我對錶執行插入、更新和刪除。
我不能使用聚集列儲存索引,因為 Data2 列是
varbinary(max)
. 我嘗試使用非聚集版本,但查詢計劃只使用聚集索引。我確實用
FULLSCAN
. 有一些維度比其他維度受到更多打擊。我之前嘗試過聚集索引中維度的順序,但它仍然高估了行數。帶計劃的完整查詢:https ://www.brentozar.com/pastetheplan/?id=HyLHtXDVX
我看到它的方式 - 問題是糟糕的 SQL,非常糟糕。
以。。開始:
$$ DIMENSION3 $$在 (48) 和
如果您有一個元素,則生成 Where,而不是 IN。
但更糟糕的是:
$$ DIMENSION10 $$IN (1, 235, … (可能是 1000 個數字)) AND
沒有關於 IN 的統計資訊,因此它最適用於較小的選擇。在這種情況下,最好用 STATISTICS 創建一個臨時表並在其中載入值,然後用某種子選擇替換 IN。這樣,查詢優化器實際上知道他所面臨的(在選擇性方面)並且可能決定以不同的方式接近。
否則有兩件事適合你;)
- 獲得體面的硬體;)然後可能在記憶體表中?
- 意識到分析服務是有原因的。
像這樣的查詢確實延伸了 SQL Server。雖然它取得了進展,但這正是分析伺服器多維數據集的用途。