Sql-Server-2008-R2

SQL Server - Varbinary 列 - 極慢的統計資訊更新

  • November 23, 2019

我的數據庫中有一個表,我們將其用作文件儲存,文件本身儲存在一個varbinary列中,直到最近,這一切似乎都執行良好,我們注意到該表的一個實例在插入語句上基本上“卡住”了.

檢查sys.dm_os_waiting_tasks顯示插入語句觸發了統計資訊更新,並且此統計資訊更新花費了長時間。(17 分鐘)。

這是我們發現執行的語句:

SELECT StatMan([SC0], [LC0]) FROM 
  (SELECT TOP 100 PERCENT CONVERT([varbinary](200), 
       SUBSTRING ([Data], 1, 100)++substring([Data], 
       case when LEN([Data])<=200 then 101 else 
       LEN([Data])-99 end, 100)) AS [SC0], 
       datalength([Data]) AS [LC0] 
   FROM [FileSystem].[FileData] WITH 
   (READUNCOMMITTED) ORDER BY [SC0] ) AS _MS_UPDSTATS_TBL

該表中大約有 2000 行,如下所示:

CREATE TABLE [FileSystem].[FileData]
(
[Id] [uniqueidentifier] NOT NULL CONSTRAINT [DF__FileData__Id__09DE7BCC] DEFAULT     (newsequentialid()),
[Data] [varbinary] (max) NULL,
[FileHash] [nvarchar] (4000) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
[FileSize] [bigint] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
ALTER TABLE [FileSystem].[FileData] ADD CONSTRAINT [PK_FileData] PRIMARY KEY     CLUSTERED  ([Id]) WITH (STATISTICS_NORECOMPUTE=ON) ON [PRIMARY]
GO

我們知道這個表很奇怪,我們小心翼翼地只用聚集索引查找來解決它。

目前,我們只是禁用了該表的自動統計生成,但我想知道這是否真的是最佳實踐。如果沒有最新的統計資訊,性能最終會成為問題嗎(請記住,該表僅由其聚集索引解決)?

更新:

好的,我很確定我們已經找出導致統計數據生成的原因:

GO CREATE PROCEDURE [FileSystem].[FileData_AppendNewData_Easy] 
   (@fileDataId  uniqueidentifier ) 
WITH EXECUTE AS CALLER AS 
BEGIN 
  declare @testValue varbinary(max); 

  set @testValue = 0xabcedf012439; 

  Update FileSystem.FileData 
  set Data.Write(@testValue, null, null) 
  where Id = @fileDataId ;
END

這是導致問題的過程的簡化版本,似乎Data.Write導致數據列上的某種隱式謂詞?好吧,這解決了這個謎團,儘管我仍然不確定禁用此表的統計資訊可能會產生什麼影響,有人可以對此發表評論嗎?

這可以通過另外兩種方式解決:

  1. 啟用非同步自動更新統計和數據庫級別(不是我的偏好)。如果您的生產因為這個問題而被卡住,那麼這是快速修復,因為它是即時的,但它會全域影響數據庫並且可以生成低於標準的查詢計劃,因為該計劃是在統計資訊更新之前生成的。
ALTER DATABASE [DatabaseName] SET AUTO_UPDATE_STATISTICS_ASYNC ON WITH NO_WAIT
  1. 刪除自動生成統計資訊並將其替換為手動創建的無需重新計算的統計資訊。缺點是,雖然這是一種外科手術方法,但創建統計數據需要一些時間並且會導致阻塞。
DROP STATISTICS [dbo].[TableName].[_WA_Sys_00000004_7D78A4E7]
GO
CREATE STATISTICS [_Manual_Stat_Name] ON [dbo].[TableName]([Column]) WITH NORECOMPUTE;
GO

當我們被迫處理類似的問題時,我們先使用選項 1,然後使用選項 2。在“綠色區域”期間,我們恢復了數據庫範圍的設置,然後將列的統計資訊替換為手動創建的 NORECOMPUTE 統計資訊。

目前,我們只是禁用了該表的自動統計生成,但我想知道這是否真的是最佳實踐。

根據 Microsoft 對此Connect 項目的評論,是的,它是:

感謝您的回饋。我們將在未來的版本中考慮這一點。請考慮暫時在該列上使用手動統計更新並禁用自動更新。如果您無法提出解決方法,請聯繫 Microsoft 客戶支持服務,這對您來說是一個關鍵問題。

最好的問候,

Eric Hanson

項目經理

SQL Server 查詢處理

在 SQL Server 2012 中,該行為已更改,因此UPDATE Table SET x.WRITE不再觸發統計資訊創建。其他類型的查詢可能仍會導致創建統計資訊,因此禁用自動統計資訊可能仍然是正確的做法。

我最喜歡的快速創建不會自動更新的空白統計數據的方法是:

CREATE STATISTICS stats
ON dbo.Test (target_column)
WITH
   SAMPLE 0 ROWS, 
   NORECOMPUTE;

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