Sql-Server

為什麼我的統計數據這麼快就過時了?

  • December 27, 2019

我有一個大表(3 億行),每天添加大約 100 萬行。這是時間序列數據,所以我有以下設置:

CREATE TABLE Readings (
   Id INT PRIMARY KEY,
   TrackerId INT,
   DateProcessed DATETIME,
   -- About 10 other columns of data
)

CREATE INDEX IX_TrackerId_DateProcessed
ON Readings (
   TrackerId,
   DateProcessed
) INCLUDE (
   -- all the other columns
) WHERE (
   TrackerId IS NOT NULL
)

當我們查看數據時,我通常會執行如下查詢:

SELECT Latest.*
FROM Trackers
CROSS APPLY (
   SELECT TOP 1 *
   FROM Readings
   WHERE TrackerId = Trackers.Id
   ORDER BY DateProcessed DESC
) Latest

這曾經工作得很好。現在,生成查詢計劃需要很長時間,即使我明確告訴它使用索引。到目前為止,我發現的唯一解決方案是使用以下命令更新表的統計資訊:

UPDATE STATISTICS Readings

這大約需要十分鐘才能執行,然後選擇查詢執行良好,但只執行一天。然後我必須再次更新統計資訊。為什麼統計數據過時如此之快,我能做些什麼來防止這種情況發生?

值得一提的點:

  • 我只追加到表中,我從不更新或刪除行
  • 有一些舊行的 tracker id 值為空,但不會再添加
  • 數據庫以兼容級別 14 執行
  • 我無法在 Azure SQL 中啟用跟踪標誌 2371

評論中問題的其他答案

更新統計資訊前的預估查詢計劃

更新統計資訊後的預估查詢計劃

更新統計數據之前和之後的計劃對我來說是一樣的。問題在於我得到了一個糟糕的查詢計劃,而在於獲得該計劃*需要多長時間。*在更新統計數據之前,我不得不等待兩分鐘的計劃。更新統計數據後,它立即得到了計劃。

在寫這篇文章時,我剛剛意識到等待查詢實際上會更快,讓記憶體來完成工作,而不是更新統計資訊,但這仍然不能解決問題。此查詢是在 Entity Framework 中執行的,超時時間為 30 秒,因此兩分鐘仍然太長。

自動更新統計資訊所花費的時間包含在編譯時間中。統計資訊更新需要 10 分鐘,觸發自動統計資訊更新的查詢的編譯時間包括該時間 - 這就是查詢時不時需要超過 10 分鐘的原因。

根據文件,自動統計更新的修改門檻值為

sqrt(table cardinality * 1000)

使用您的數字(300,000,000 行),您達到了 547,722 次修改的門檻值。

由於每天要添加 1,000,000 行,因此您必須每天兩次左右自動更新統計資訊。

由於您的查詢估計在統計資訊更新前後都很好,因此一種可能的解決方案是啟用數據庫級別AUTO_UPDATE_STATISTICS_ASYNC設置。這仍然讓 SQL Server 自動更新統計資訊,但它是非同步完成的(因此查詢不必等待它發生):

ALTER DATABASE [Live] 
SET AUTO_UPDATE_STATISTICS_ASYNC ON;

請注意,這會影響整個數據庫,而不僅僅是該表/統計資訊。

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