背景: 在统计自动更新设置为ON时(默认设置),当更新次数达到一定阀值后便会触发自动更新。
本文通过一些测试来探究SQL SERVER 如何追踪数据更新情况和如何计算更新次数。
--==========================================
--可以使用以下系统表来查看列变化情况--sys.system_internals_partition_columns--sys.sysindexes--sys.sysrscols(需要使用DAC)--==========================================--生成测试表和索引DROP TABLE dbo.TB001GOCREATE TABLE dbo.TB001( ID INTIDENTITY(1,1) NOT NULL, C1 INT, C2 INT)GOALTER TABLE dbo.TB001ADD CONSTRAINT PK_TB001PRIMARY KEY(ID)GOCREATE INDEX IX_C2 ON dbo.TB001(C1)--===========================================--插入10 条数据INSERT INTO TB001(C1,C2)SELECT 1,1GO 10--============================================--数据修改不会即时更新到系统表中,需要使用CHECKPOINT--来将更新flush到系统表中CHECKPOINTGO--============================================--使用sys.system_internals_partition_columns来--查看数据的变更(无法获得非聚簇索引上的变化)SELECT p.[object_id], p.[index_id], pc.[partition_column_id], pc.[modified_count]FROM sys.system_internals_partition_columns pcJOIN sys.partitions p ON pc.[partition_id] = p.[partition_id]WHERE p.[object_id] = OBJECT_ID('dbo.TB001');GO--================================================
--查看非聚簇索引上的变化SELECT I.name,I.rowcnt,I.rowmodctrFROM sys.sysindexes IWHERE I.id=OBJECT_ID('dbo.TB001');--================================================
--重建索引ALTER INDEX [PK_TB001] ON [dbo].[TB001] REBUILDGOALTER INDEX [IX_C2] ON [dbo].[TB001] REBUILDGO--===============================================--重建索引后发现被索引的列的值没有发生变化SELECT p.[object_id], p.[index_id], pc.[partition_column_id], pc.[modified_count]FROM sys.system_internals_partition_columns pcJOIN sys.partitions p ON pc.[partition_id] = p.[partition_id]WHERE p.[object_id] = OBJECT_ID('dbo.TB001');GO--================================================
--查看非聚簇索引上的变化--重建索引后,索引变化rowmodctr的值被清零SELECT I.name,I.rowcnt,I.rowmodctrFROM sys.sysindexes IWHERE I.id=OBJECT_ID('dbo.TB001');GO--================================
--对一行数据更新110 遍UPDATE TB001SET C1=2WHERE ID=1GO 110CHECKPOINT--================================================--查看非聚簇索引上的变化--发现单行数据被修改110 次,rowmodctr被置为 110--即使值未发生变化,也被记录为一次修改 SELECT I.name,I.rowcnt,I.rowmodctrFROM sys.sysindexes IWHERE I.id=OBJECT_ID('dbo.TB001');GO--==============================
--更新统计sp_updatestats--================================================--查看非聚簇索引上的变化--统计被更新后,rowmodctr被重置为0SELECT I.name,I.rowcnt,I.rowmodctrFROM sys.sysindexes IWHERE I.id=OBJECT_ID('dbo.TB001');GO
使用脚本查看
--查看最后统计更新的时间及最后一次更新后数据更新的次数SELECT T.[name] AS TableName , S.[name] AS StatsName , P.last_updated AS LastUpdatedTime , P.[rows] AS TableRows , P.rows_sampled AS SampledRows , P.modification_counter AS ModifiedRowsFROM sys.tables T INNER JOIN sys.stats S ON T.[object_id] = S.[object_id] OUTER APPLY sys.dm_db_stats_properties(S.[object_id], s.[stats_id]) AS P--WHERE T.[name]=''
总结:
1. 使用sys.system_internals_partition_columns来查看聚簇索引上的更新次数2. 使用sys.sysindexes来查看非聚簇索引上的更新次数3. 重建索引会导致更新次数数据被重置为零(建议在索引重建后更新统计)4. 更新次数计算的是更新操作的次数(即使值未发生变化,也被记录为一次修改)5. 在统计被更新后,更新次数被重置为零
参考链接:
照例来张图: