如果相对于行数的插入点很少,则索引维护策略

Jus*_*ant 4 sql-server sql-server-2008-r2 index-tuning

在 SQL Server 2008 R2 中,我在具有 1 亿多行的多个表上有一个非聚集覆盖索引。该表有几千个“插入点”,所有新插入都在其中发生。这意味着无论填充因子如何,我很快就会在每个插入点处出现页面拆分和碎片,并且表格中的其他任何地方都不会出现碎片或拆分。不幸的是,查询总是包含新行,因此索引的碎片区域。

  • 当页面拆分但插入在拆分后按顺序继续时会发生什么?有没有办法告诉 SQL Server 进行拆分,为后续插入留出大量额外空间,而不会在现有页面上浪费空间,并且填充因子对于大多数页面来说永远不会被填充?
  • 用于此类索引的良好索引维护策略是什么?
  • 有没有一种很好的自动化方法来识别这样的表,其中碎片严重但不统一?这些表的整体碎片化程度不超过 5%。
  • 我应该考虑更改索引模式吗?

这是有关该问题的更多信息。索引都看起来像这种模式(为了清楚起见,下面进行了简化):

CREATE TABLE Foo (
    id int identity(1,1) PRIMARY KEY CLUSTERED, 
    foreign_key int, 
    log_time datetime, 
    ...)     
CREATE NONCLUSTERED INDEX on Foo (foreign_key, log_time) INCLUDE (...)
Run Code Online (Sandbox Code Playgroud)

此表上的查询始终采用以下形式:

WHERE log_time > getdate()-70 AND foreign_key IN (select ...)
Run Code Online (Sandbox Code Playgroud)

其他事实:

  • 大约有 5,000 个外键值,每个值都有 10,000 行。
  • 平均行大小为 55 字节,这意味着每页大约 150 行
  • 所述IN过滤器通常包括10%-50%foreign_key的值的行和日期过滤器包括20%-40的行的%。平均值约为所选行总数的 15%。
  • 索引是查询的覆盖索引,因此不需要聚集索引访问。

Tho*_*ger 5

一个页面拆分是一个页面拆分您无法控制 SQL Server 在需要分页时执行的操作。这不是一个可变的和可配置的设置。当 SQL Server 需要拆分页面时,它会将大约一半的数据放在一页中,另一半放在新页中。

如果您在索引中有“多个”插入点,导致索引中的热点经历许多页面拆分和大量碎片,那么您无法用当前的设计来缓解这种情况。 听起来您的数据分散方式可能是您问题的根源。如果插入索引的中间,则会导致页面拆分/碎片化。

您可以做几件事,具体取决于您的“插入点”的可预测性。您可以利用表分区,这将允许您在特定分区(或多个分区)上重建索引。这将阻止冷数据接收维护,并最大限度地减少重建热分区和碎片分区的持续时间。

根据您的版本,您还可以利用在线索引重建操作来减少对这个维护过程的可用性影响。