优化表/索引以获取最新行(按额外的一列过滤)

Eug*_*e O 6 performance index database-design sql-server sql-server-2012

我有一个 SQL Server 表(SQL Server 2012 SP3 标准版),它存储了不同组织的一堆配置信息(基本上是文本 blob)。架构是这样的:

[ConfigurationID]       INT IDENTITY (1,1) NOT NULL,
[OrganizationID]        INT NOT NULL,
[TimestampUtc]          DATETIME NOT NULL,
[ConfigurationData]     NVARCHAR (MAX) NOT NULL,
[ChangedBy]             NVARCHAR (256) NOT NULL,
[Comment]               NVARCHAR (MAX) NOT NULL,
[ChangeType]            INT NOT NULL
Run Code Online (Sandbox Code Playgroud)

TimestampUtc会一直增加(我将永远不会成为插入“回过时”的条目到表),行永远不会被更新(我只插入新行)。对于某些OrganizationIDs 会有很多行,对于一些非常少,并且OrganizationID任何时候都可能会插入一个新行。

如果需要,我可以保证的唯一性TimestampUtc(但如果有一个不需要的解决方案会很棒)。

INSERT 相对较少(每天最多几十次,但通常比这少得多),读取非常频繁(基本上是对我的应用程序的每个 Web 请求)。

我的目标是:

  • 无论表的大小如何,获取给定ConfigurationData的最新信息都应该非常快TimestampUtcOrganizationID
  • INSERT 性能并不重要,但我想尽可能避免可怕的索引碎片(所以我对唯一聚集索引的第一个想法OrganizationID ASC, TimestampUtc DESC可能不是一个好主意)。

问题

我知道我可以非规范化并只将最新ConfigurationData值存储在一个表中,并将先前值的历史日志存储在另一个表中,但是仅使用一个表是否可以实现我的目标?最好的方法是什么?(即最好的索引结构是什么?我需要更改有关表架构等的任何内容吗?)

小智 1

鉴于插入率较低,您建议的索引将完全没问题,并且非常适合使用目标。

给定填充因子为 100% 的新索引,以及每个组织足以填充一页的历史记录,每个组织的第一个后续插入将出现页面拆分。但是,在新页面填满之前,该组织不会再进行页面拆分。
即使这些分裂和碎片也可以通过从 <100 填充因子开始并定期重组来减轻。

Aaron 关于使用非聚集的想法可能是因为这将允许您聚集在始终升序的标识列上,确保您将获得的唯一拆分和碎片位于非常紧凑的单独索引中。但我怀疑他只是在你非常希望避免碎片化的情况下提到这一点,而不是在这种情况下真正必要的事情。