從未使用的聚集主鍵與多列上的非聚集主鍵
我正在為客戶總計進行表設計,並試圖對主鍵做出決定。我打算使用帶有聚集索引的代理標識列,但永遠不會使用此列。候選主鍵列是 CustomerNumber + AccountNumber,因為這些是每行的唯一標識符,但不會按順序插入。
基本上,每天都會執行一份報告,該報告將使用最近的購買總額和總日期更新每個 CustomerNumber + AccountNumber 記錄。
完全刪除 CustomerTotalID 並讓 CustomerNumber + AccountNumber 成為具有非聚集索引的 PK 是否有意義?
CREATE TABLE CustomerTotals ( CustomerTotalID INT IDENTITY(1,1), CustomerNumber INT, AccountNumber INT, PurchaseTotal DECIMAL(10,2) TotalDate DATE, CONSTRAINT [PK_CustomerTotals] PRIMARY CLUSTERED ( CustomerTotalID ASC ) )
如果您要在不是主鍵的東西上進行集群,那麼我會確保這些列是謂詞中最常用的。不過要注意的一件事是,如果您的聚集索引是非唯一的,那麼 SQL Server 將不得不添加一個唯一性並且不是免費提供的,此連結有更多詳細資訊https://www.mssqltips.com/sqlservertip /2082/understanding-and-examineing-the-uniquifier-in-sql-server/但 tl;dr 它們是 4 個字節,如果重複組合過多,可能會中斷。
我個人喜歡 PK 的代理身份列,因為:
- 它很窄,所以更容易存放
- 將單個列作為外鍵發布更簡單
- 在表上容易看到的唯一值可以幫助診斷任何可能的未來數據問題。
第 1 點也使其可用作聚集索引,因為它可以比
CustomerNumber
和更便宜地引用AccountNumber
。話雖如此,沒有什麼可以替代測試您擁有的所有選項並查看最適合您的工作負載的選項。
完全刪除 CustomerTotalID 並讓 CustomerNumber + AccountNumber 成為具有非聚集索引的 PK 是否有意義?
刪除代理鍵確實有意義,因為您不會使用它。
自然鍵*(CustomerNumber, AccountNumber)*上的主鍵可能應該是集群的,而不是非集群的。
如果從成本的角度來看是有意義的,查詢優化器將為大型插入引入排序。使用非聚集 PK,您將插入堆和單獨的非聚集索引。
擔心填充因子、重建和碎片通常被誇大了。請參閱為什麼對索引進行碎片整理沒有幫助。
如果不經常插入新的*(CustomerNumber, AccountNumber)*值,則聚集索引的碎片和頁面拆分完全不是問題。
如果僅通過CustomerID或CustomerID/AccountNumber查詢表,則使聚集索引不費吹灰之力。