Sql-Server

用代理替換複合鍵

  • February 9, 2013

我有下表,其中有幾百萬行,並且幾乎所有時間都存在 99% 的碎片。我的計劃是插入一個 IDENTITY 欄位作為代理鍵來替換目前的複合 6 欄位主鍵,然後使目前鍵成為引用完整性的唯一鍵並重新創建索引。

   CREATE TABLE [dbo].[Autocompleter](
       [CountryId] [int] NOT NULL,
       [ProvinceId] [int] NOT NULL,
       [LocationId] [int] NOT NULL,
       [PlaceId] [int] NOT NULL,
       [EstabId] [int] NOT NULL,
       [LocaleId] [int] NOT NULL,
       [Title] [varchar](400) NOT NULL,
       [Hotels] [int] NULL,
       [AlternateTitles] [varchar](4000) NULL,
       [EnableHotels] [bit] NOT NULL,
       [EnableHolidays] [bit] NOT NULL,
       [DisplayPriority] [int] NOT NULL,
    CONSTRAINT [PK_autocompleter_1] PRIMARY KEY CLUSTERED 
   (
       [CountryId] ASC,
       [ProvinceId] ASC,
       [LocationId] ASC,
       [PlaceId] ASC,
       [EstabId] ASC,
       [LocaleId] ASC
   )

有什麼我應該注意的問題嗎?如果它是一個身份欄位,我認為這不應該破壞插入表中的程式碼(只要它明確指定列)

我計劃在代理鍵上創建一個新的聚集索引,然後將 6 個欄位上的目前聚集索引設為 NC 索引。

閱讀 Kimball 維度建模,使用代理鍵,特別是 IDENTITY,將有助於減少由頁面拆分引起的碎片,因為您將在葉子頁面的末尾附加行而不是嘗試將它們插入中間,如果鍵不按索引的順序(升序或降序取決於索引的定義方式)。

但是,如果代理鍵不會用於與其他表的連接或 WHERE 條件中,那麼在初始數據導入後,將代理鍵用作聚集索引可能不會提供任何額外的好處。如果您保留複合聚集鍵,則在導入之前按六列複合鍵的順序對源數據進行排序應該可以避免您看到的頁面拆分碎片。

至於聚集索引的選擇,最佳候選者可能是用於 WHERE 條件或連接的最常見/關鍵查詢中的列。如果結果集中需要,使用 NCI 將需要書籤查找來獲取表中的剩餘值。

在 SQL Server 的儲存級別(可能在所有 dbms 中),沒有任何表。在 SQL Server 的儲存級別,您有兩件事之一。(我想。)你有

  • 堆加上其他一些東西,或者
  • 聚集索引加上其他一些東西。

堆被隨機分佈的插入、更新和刪除碎片化。據我所知,微軟沒有提供任何直接的方法來對堆進行碎片整理。

但是create clustered index重寫了堆。所以你可以創建一個聚集索引來重寫堆,然後刪除聚集索引。我不認為這是對堆進行碎片整理的直接方法,因為重寫堆是創建聚集索引的副作用。


這是我還不明白的。(這可能是非常基礎的知識,但我在 SQL Server 上工作的不多。)

整個表每天都會重新載入。除了每天重新載入之外,它永遠不會更新。那麼碎片化從何而來?填充因子選擇不當?對於這樣的表格,填充因子 100 會是一個合理的選擇嗎?

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