Sql-Server
在非聚集索引列上使用日期範圍的慢速執行查詢
我有一個執行速度非常慢的查詢,我已將問題隔離到以下 SQL。
SELECT ... FROM TableA a(nolock) inner join TableB b with(nolock) on (b.Id = a.Id AND b.Date>= isnull(@timestamp_start, '17530101') AND b.Date < isnull(@timestamp_end, '99991231'))
- a = 200萬+行
- b = 200 萬+ 行
- b.Id => 索引,唯一,非聚集
- a.Id => 索引,唯一,非聚集
- b.Date => 索引,非唯一,非聚集
即使在一天的日期範圍內,這也需要幾分鐘而不返回結果。
更新:
生產伺服器上的估計執行計劃向我展示了這一點,這表明在查詢開始附近發生了對巨大表 (TableA) 的完整掃描,而不是用於在 WHERE 中過濾的 TableB.date 範圍。為什麼會發生這種情況,如何強制查詢首先在我的日期範圍內進行過濾?
該計劃與此查詢有關,詳細內容為:
SELECT ... FROM TableA a(nolock) inner join TableB b with(nolock) on (b.Id = a.Id AND b.Date>= isnull(@timestamp_start, '17530101') AND b.Date < isnull(@timestamp_end, '99991231')) inner join TableC c with(nolock) on c.Id2 = s.Id2 and c.Id3 = a.Id3 and c.Id = b.Id inner join TableD d with(nolock) on (a.DealId = d.Id and d.Id3 = s.Id3 AND (@myparam is null OR d.ProviderName = @myparam)) inner join TableE e with(nolock) on (e.Id = d.Id AND (@myparam2 is null OR e.Id = @myparam2))
您應該查看實際計劃,而不是您在此處發布的估計計劃。
您的計劃將 NL 與聚集索引 + 排序中的查找一起使用,因此很明顯伺服器為您的過濾器估計的行數很少。當您查看實際計劃時,而不是 100-1000 行看到有 500.000 行從您的第一次索引查找中出去,這是一個問題。這意味著應該使用全掃描,並使用雜湊連接而不是合併。
所以請用實際計劃更新您的文章
好的,我發現對於像這樣的複雜查詢,由於 SQL Server 將記憶體最後一個執行計劃,以後的查詢最終可能會被優化得很差。
我之前使用其中一個參數執行查詢,並且執行計劃正在針對後續查詢中的該場景進行優化。通過在查詢末尾添加以下內容,SQL Server 被迫重新編譯查詢的執行計劃,從而修復了性能:
OPTION (RECOMPILE)