<b>問題描述</b>
建立一個新表時,一個非常重要的設計原則就是建立還是不建立聚集索引的決定。沒有聚集索引的表被稱為堆,擁有聚集索引的表叫聚集索引表。
聚集索引表比堆表擁有一些好處(優勢),比如聚集索引表是基于聚集索引鍵順序存儲的,正因為如此,是以通過聚集索引可以快速查找某一行;可以通過重建聚集
索引重新組織資料。當你對表進行insert、update、delete等操作時可能會使實體資料變得碎片化,這種碎片化可能會導緻你浪費大量資料庫存
儲空間,因為本來可以存儲在一頁的資料,需要存儲在多個資料頁上(pages),那麼,我們該怎麼做呢?
<b>解決方案</b>
我們要解決的首要問題是發生在資料庫正常活動中的碎片。你的表是否擁有聚集索引
将決定您是否可以在資料庫實體層面很容易的解決碎片化問題。因為堆或聚集索引決定你表資料的實體存儲,每個表要麼擁有一個聚集索引或沒有一個聚集索引,所
以每個表要麼是一個堆或聚集索引表。
讓我們來看看一個堆表和聚集索引表之間的差異:
heap
資料存儲沒有任何特定的順序。
不能快速的找到特定資料,除非也有非聚集索引。
資料頁之間沒有指針關聯,是以順序通路需要重新傳回到索引配置設定映射(iam)頁
既然沒有聚集索引,是以不用額外的時間去維護聚集索引。
既然沒有聚集索引,是以不用額外的空間去存儲聚集索引樹。
堆表的索引在sys.indexes目錄視圖的記錄的index_id字段值為0
clustered table
資料存儲基于聚集索引鍵順序存儲。
如果查詢時使用聚集索引列,資料可以基于聚集索引鍵快速檢索到。
資料頁之間有指針連結,可以更快速的順序通路。
當insert、update、delete操作時,需要額外的時間維護聚集索引。
需要額外的空間存儲聚集索引樹。
聚集索引表在sys.indexes目錄視圖的記錄的index_id值為1.
是以,基于以上你可以看到有一個表是否具有聚簇索引将決定表的一些根本性的不同之處。
<b>碎片化問題</b>
所有的表都會發生的一個問題就是碎片化的問題。根據不同的操作,比如删除,插入和更新,您的堆表和聚集索引表将會變得越來越碎片化。碎片化很多時候取決于insert、update、delte這類操作,以及用作聚集索引的鍵。
如果您的堆表隻有insert操作,你的表不會變得碎片化,因為隻有新的資料寫入。
如果您的聚集索引鍵是連續的,比如一個自增字段。并且對該表你隻有insert操作,這同樣也不會變得碎片化,因為新的資料總是寫在聚簇索引的後面。
但是,如果你的表是一個堆或聚集表,并有大量的插入,更新和删除操作,資料頁碎片化可能會變得越來越嚴重。這不僅會導緻浪費額外的空間,而且需要讀取額外的資料頁來滿足查詢。
當一個表在堆上建立,sql server不會強迫在那個新資料頁(new
page)寫入資料。每當新的資料寫入時,該資料總是寫在表的末端,或者配置設定給該表中的下一個可用的頁面上。當資料被删除時,資料頁上的空間釋放出來,但
它不重複使用,因為新資料總是寫入到下一個可用的頁面。
具有聚簇索引,根據索引鍵,新的記錄可能會被寫入到現有的頁面,這些頁面可能存在的空閑的空間或者有可能需要分割成多個頁面的頁面。以便插入新的資料。删
除時會發生同樣的問題時,與一個堆對比,但是這些空閑間可以再次使用,如果資料需要插入到具有可用空間的現有頁面中的一個。
是以,基于以上叙述 ,你的堆表可能變得比你的聚集表更加支離破碎。
檢視碎片化
解決碎片化
聚集索引表
堆表
對于堆表來說,這個不太容易的。您可以采取以下不同的方法來解決碎片問題:
對堆表建立一個聚集索引
建立一個新的堆表,并根據某種順序将舊表中的資料插入到新表
導出資料,截斷表并導入資料傳回到表
附加資訊
當你通過企業管理器或management
studio建立一個新表并在新表中指定一個主鍵,管理工具會自動為其建立一個聚集索引,但可以被重寫。當通過腳本建立一個新表時,你需要明确指定建立聚
集索引。是以,正是由于主鍵關系,你大部分的表将會擁有一個聚集索引,但如果建立表時,你不指定一個主鍵或建立聚集索引,該表的資料将被存儲為一個堆。
<b></b>
下一步
維持表和索引的碎片化在控制範圍内是保持資料庫最佳性能的一個關鍵過程。現在你可以明白一個堆與聚集索引表在解決碎片化上的不同,看看你的表結構,看看你需要解決這些問題。
即使對所有表一個星期做一次索引重建,你的堆表是永遠不會解決瑣碎化問題的,是以你需要想出另一種政策來處理堆表的碎片問題。
一起來看看這些相關技巧:
基于上述論證,似乎所有的表都應該有一個聚集索引。在大多數情況下是這樣,但也可能由于某種原因,你不希望有一個聚集索引。一個原因可能是該表隻有insert操作,例如一個日志記錄的表。但是毫無疑問,有聚集索引一定好過沒有聚集索引