Sql-Server

在非聚集索引列上使用日期範圍的慢速執行查詢

  • August 3, 2017

我有一個執行速度非常慢的查詢,我已將問題隔離到以下 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)

引用自:https://dba.stackexchange.com/questions/182561