随着更多行被删除,索引碎片增加

dsu*_*sum 4 index sql-server-2005 sql-server fragmentation

我有一个包含超过 1800 万条记录的表。我有一个每天从该表中清除数据的过程。索引碎片很少。

该表具有高事务吞吐量。它每秒存储大约 3 到 5 条新记录,因此我们知道清除该表的旧记录需要很快。

删除语句是这样的:

Delete top 1000 
From MyTable 
Where CreationDate < 'Some Date'
Run Code Online (Sandbox Code Playgroud)

理想情况下,我们会一直运行它,直到无法删除更多行。

对于前 600 万条记录,删除过程进展顺利,但随着时间的推移,删除开始变慢,直到影响访问同一表的其他应用程序。此外,许多外键索引变得碎片化。

我的问题是:

  1. 删除大量行会导致外键索引碎片化吗?(即索引依赖表)
  2. 删除是否因为外键索引碎片化而变慢?(较慢的参考数据查找)
  3. 是否有一种平衡策略可以保持删除和外键索引的性能都很高?

我使用的是 SQL Server 2005 标准版。

[更新] 我在这里包含了更多信息实际表名称为“VehicleLocation”关键列:

  • VehicleLocationKey (PK, char(36), not null)
  • AgencyVehicleKey (FK, char(36), not null)
  • 分配键(FK,字符(36,空)
  • EmployeeKey (FK, char(36), null)

索引

  • VehicleLocation_AssignmentKey(非唯一、非集群)
  • VehicleLocation_CreationDate(非唯一,非聚类)
  • VehicleLocation_MessageGenerationDate(非唯一,集群)
  • VehicleLocation_pk(唯一,非集群)

VehicleLocation 的对象依赖关系(约 1050 万行)

  • VehicleLocationAPC(~76000 行)
  • VehicleLocationFare (0 行)
  • VehicleLocationGF(0 行)
  • VehicleLocationInpt(0 行)
  • VehicleLocationOBD(~ 15000 行)
  • VehicleLocationTP(~830 万行)

以上所有表在其主键和 VehicleLocationKey (FK) 表上都有索引。

此外,我们使用 GUID 作为主键(坏主意,但它是遗留的)。最重要的是,我看到 VehicleLocationTP 索引的碎片率为 96%,这是非常高的。

gbn*_*gbn 6

这不是分裂。

当然会产生碎片,但删除只会创建剩余页面的“孤岛”,这比 GUID/集群键 INSERT 碎片更不邪恶。

如果您 PK 是 IDENTITY,那么CreationDate应该粗略地跟踪它,以便您实际上删除连续行的块。

  1. 你有索引吗 CreationDate
  2. 你有删除级联吗?
  3. TOP 1000 是单笔交易吗?

对于第 3 点,在事务内执行循环是没有意义的:是这样吗?

在某些时候,如果您删除了足够多的行,则可能需要更新统计信息,但我认为不是这样。

其他选项:

  • 为什么不使用 TRUNCATE TABLE,用 EXECUTE AS OWNER 包装在存储过程中
  • 将同义词用于穷人的分区