Sql-Server

優化表/索引以獲取最新行(按附加列過濾)

  • May 7, 2020

我有一個 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

TimestampUtc永遠增加(我永遠不會在表中插入“回溯”條目),並且行永遠不會被更新(我只是插入新行)。對於一些OrganizationIDs 會有很多行,對於一些非常少的行,並且OrganizationID任何時候都可以插入新行。

如果需要,我可以保證的唯一性TimestampUtc(但如果有一個不需要的解決方案會很棒)。

INSERT 相對較少(每天最多幾十次,但通常要少得多),讀取非常頻繁(基本上是在對我的應用程序的每個 Web 請求上)。

我的目標是:

  • 無論表的大小如何,獲取給定ConfigurationData的最新資訊都應該非常快TimestampUtc``OrganizationID
  • INSERT 性能無關緊要,但如果可能的話,我想避免可怕的索引碎片(所以我對唯一聚集索引的第一個想法OrganizationID ASC, TimestampUtc DESC可能不是一個好主意)。

問題

我知道我可以非規範化並將最新的值儲存ConfigurationData在一個表中,並將以前值的歷史日誌儲存在另一個表中,但是僅使用一個表就可以滿足我的目標嗎?最好的方法是什麼?(即最好的索引結構是什麼?我是否需要更改有關表架構等的任何內容?)

鑑於插入率低,您提出的索引將完全沒問題,並且非常適合使用目標。

給定一個填充因子為 100% 的新索引,並且每個組織有足夠的歷史記錄來填充一個頁面,每個組織的第一個後續插入將有一個頁面拆分。但是,在新頁面填滿之前,該組織不會再拆分頁面。

即使是這些分裂和碎片也可以通過從 <100 填充因子開始並定期重組來減輕。

Aaron 關於使用非集群的想法可能是因為這將允許您在始終升序的標識列上進行集群,確保您將獲得的唯一拆分和碎片位於一個非常緊湊的單獨索引中。但我懷疑他只是在您非常希望避免碎片化的背景下提到這一點,而不是在這種情況下真正需要的東西。

如果更改表並為活動記錄添加標誌,則可以使用過濾索引,在這種情況下,IsActive=1 的 OrganizationID 是唯一的。當然,您必須先更新組織的目前活動記錄,然後才能插入新的活動條目。

CREATE UNIQUE INDEX UI_test ON dbo.test (OrganizationID) WHERE IsActive=1

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