如何使用非順序插入索引複合主鍵?
我有一個複合主鍵,包括一個日期時間、一個位置 ID 和一個 2 個字元的程式碼。這是唯一標識我的表的每一行的鍵。
我知道這個表的使用會插入一年前的一周數據,然後是今年一周的數據。因此,當主鍵來回跳轉時,表很可能會變得碎片化。
我想知道在這種情況下可以採用哪種索引策略。我的直覺是預設的聚集索引是一個壞主意,我應該用非聚集索引替換它,這將使重建更容易。
如果您擔心碎片,您的伺服器上是否有解決該問題的維護解決方案,例如SQL Server 維護解決方案 - Ola Hallengren?
問題:
- datetime 數據類型是 date、smalldatetime、datetime、datetime2(0-2)、datetime2(3-4)、datetime(5+) 還是?
- LocationId 數據類型是 tinyint、smallint、int、bigint 或 ?
- 字元程式碼數據類型是 char(2)、nchar(2) 還是?
更多問題:
- 你的表有多少行?
- 您需要一個 int 或 bigint 作為代理 id 嗎?
- 表中的其他列是什麼?
- 所有查詢都是按日期時間過濾的,還是按 locationid 和/或字元程式碼過濾的?
- 您是否總是返回整行,或者有時只是返回其中的一部分?
因為大多數人認為主鍵是集群鍵,所以我將您的問題解釋為“如何使用非順序插入索引複合集群鍵?”。
您正在考慮的情況與諸如The Clustered Index Debate和Surrogate Key vs. Natural Key之類的辯論有關。
在這種情況下,我想考慮一個影響
$$ 16? $$字節複合分群鍵與 4 或 8 字節分群鍵(int / bigint)。我的決策樹看起來像這樣:
- 我們會使用 Hekaton(記憶體中 OLTP)嗎?
- 是 => 複合鍵。逃跑。
- 否 => 好電話,繼續…
- 該表將有多少行?
數千萬,甚至更多!=> 代理鍵(可能)。
- 如果每行的數據長度是可變的而不是窄的 => 代理鍵。
- 如果行的數據長度固定且窄,並導致最佳頁面使用 => 繼續…
少於那個=>繼續…
- 如何查詢表?
datetime, location_id, character_code
=> 代理鍵的各種組合,但並不總是全部。
- 在這種情況下,您可能希望能夠
datetime, location_id, character_code
為查詢組合提供多個支持索引。聚集鍵包含在所有非聚集索引中,它越大,每個索引條目所需的空間/頁面就越多。=> 代理鍵。幾乎總是由三個
datetime, location_id, character_code
或幾乎總是由datetime
ordatetime, location_id
; 但不是location_id
沒有datetime
也不是character_code
沒有datetime, location_id
(這個表上的零個或只有幾個非聚集索引)=>繼續…
- 任何其他表會引用此表嗎?
- 是 => 代理鍵。
- 否 => 複合鍵是一個合理的選擇
即使我第一次執行上述決策樹將我引導到一個複合鍵,我也可能會使用代理鍵開始我的設計,因為擺脫它(因為它沒有被使用)比返回更容易並添加它並實現它的使用。
只是為了澄清一下,我確實發現複合鍵是更好的解決方案並且確實重構了設計以刪除代理鍵的情況。我不想給人留下代理鍵總是更好的解決方案的印象,即使它是許多設計師(包括我自己)的常見預設值。
參考:
- 一個簡單的開始 - 表創建最佳實踐 - Kimberly Tripp - 關於行大小和頁面使用率
- 不斷增加的分群鍵 - 聚集索引辯論…………再次!- 金伯利·特里普
- 聚集索引辯論仍在繼續…… - Kimberly Tripp
- 更多關於聚群鍵的考慮——聚群索引辯論仍在繼續!- 金伯利·特里普
- 那把鑰匙要多少錢?(加上 sp_helpindex9)- Kimberly Tripp
- 關於 Sql Server 我希望你知道的 101 件事 - Thomas LaRock
- SQL Server:自然鍵與代理鍵 - 數據庫日誌 - Gregory A. Larsen
- 十個常見的數據庫設計錯誤 - 簡單的談話 - Louis Davidson
- Hekaton(記憶體中 OLTP)- dbareactions.com
我不確定這是否會減少頁面拆分,但如果更改最多,我會將日期放在最後。
填充因子小於 100%。即使是 90% 或 80% 也會顯著減慢碎片化速度。
有一個維護計劃來重組/重建索引。
非聚集索引將使用更多空間,但可以提高維護效率。您可以在非聚集索引上放置唯一約束。