Sql-Server

在父/子關係中的子表上的聚集索引是最佳索引嗎?

  • February 6, 2015

聚集索引將根據索引中欄位的順序對錶中的行數據進行排序。如果是這樣,您為什麼(或不想)要在父/子關係中的子表上創建聚集索引?

讓我們假設一個經典的 order-with-orderlines 範例,在該範例中,您永遠不會在不先處理相關訂單的情況下獲取訂單。我認為在 orderid 和 orderlineid 列上都有一個聚集索引(因為聚集索引必須是唯一的)強制單個訂單的所有訂單線在物理上彼此相鄰,這將使讀取非常高效。它是否正確?如果是這樣,這種方法有缺點嗎?

您關於鄰接的假設是正確的。

如果我們以 TPC-H 為例:在LINEITEMSon 上對錶進行分群ORDERID將在磁碟上定位屬於同一LINEITEM物理相鄰的所有訂單行。這加快了獲取給定的所有訂單行的查詢ORDERID。對父級的外鍵進行分群還允許子級和父級之間的快速合併連接。

分群方法有一些缺點:

  • 整個表必須在磁碟上保持排序。如果您期望大量插入而ORDERID不是按順序生成,則頁面拆分將更加昂貴。這是你可以扔硬體的東西。
  • 如果ORDERID按順序生成,您將在表的末尾創建一個熱點。在某些數據庫引擎(例如 SQL Server)中,這是高速插入時的問題。在 SQL Server 中,這通常會以大約 5K-10K 插入/秒的速度啟動。
  • 集群索引鍵要麼必須是唯一的(例如:ORDERID, LINENUMBER),要麼用一些隱藏列填充以使其唯一。由於復合集群鍵必須存在於所有其他索引中,這使得二級非集群索引更大。
  • 當您想通過二級索引定位數據時,將表聚集儲存將強制執行 B 樹遍歷(除非二級索引覆蓋查詢)。如果您將表保留為堆,則所有其他索引將只有 8B 成本,並且您的 B 樹遍歷將減半。

在絕大多數情況下,您會希望將父級和子級都聚集在同一個前導鍵上。但是,如果您希望通過許多不同的索引訪問子表 - 可能值得考慮替代方案。

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