聚集和非聚集索引

聚集和非聚集索引

以前一直不是很注意聚集索引和非聚集索引的關係。今天因爲設計一個統計系統對性能要求要高一點,所以把聚集索引和非聚集索引進行一下重溫。同時也寫出來讓大家拍轉。

         索引,就好像一個方便快速查找的東西。就好像把物品按照一定順序排列在一個地方一樣,而索引就好像是針對這些排序編譯的一個排序目錄。

         那什麼是非聚集索引呢?

         我們還是以一本書來作爲例子,非聚集索引就好像是書的目錄,當你想找某個章節的內容的時候,你直接查看目錄,然後就能翻到你所要查找的詳細書頁去了。這樣就能大大的提高你的查詢速度。

         那爲什麼有聚集索引呢?

         還是以書來作爲例子。如果我們對書比較熟悉了,直接就能跳過查找目錄的這一操作,直接就往目標書頁翻過去了,這樣就能避免中間的查找目錄的過程,從而又再次提交了效率。

 

 

看上面的圖:

  這是一個聚集索引的一個數據結構。

索引頁:是數據庫針對所有的數據會生成一個索引頁,當你對數據進行查詢的時候,他會檢索相關的索引頁,從而找到相關的數據頁。

數據頁:是指的詳細的數據。同時需要注意的是:聚集索引的數據的物理排序都是按照索引順序進行的排序。

 

他引頁得到相關的數據的範圍,從而快速的找到詳細的目標數據。而索引頁其實他是一個樹形菜單的方式,這裏就會涉及到B+TreeB-Tree的相關的知識了。暫時還沒有詳細去看相關的資料。

舉例:

例如:我們想找到JAC這一條數據。

則數據庫則先會在 頁7找到下一集的索引頁 頁6 而 頁6則會繼續查找他下面 頁4從而找到詳細數據並返回。

 

然後我們再來看看非聚集索引的結構。


  非聚集索引和聚集索引最大的區別在於,他針對數據的索引列生成了一個已經進行了排序的索引頁。而他本身的數據在物理存儲上是沒有順序可言的。

 

也因爲這樣的結構的不同,所以聚集索引和非聚集索引有一個增加、修改、刪除時候的效率比較。

聚集所以因爲他的排序是直接建立在數據上面的,所以當你對數據進行修改(涉及到索引列的操作)操作的時候他會需要對原來的數據進行相關的排序,而非聚集索引的排序是建立在自己創建的索引上,他只需要更新自己的索引頁就好了。所以,從這點考慮,非聚集索引比聚集索引效率更高。但是因爲聚集所以他直接面對數據,在查找數據的時候不用進行排序索引頁的操作這一操作,所以他的查找效率更高。

但是在插入和刪除的時候,聚集索引比非聚集索引塊。道理和上面的差不多。

同時還有一個需要注意的問題就是:聚集索引如果你插入的列的索引列是自增的時候,你在插入的時候因爲他不需要分頁操作,所以效率會更快,但是如果你插入的數據在已經有的數據的中間,那麼他會引起一個分頁這樣的一個操作,這樣會讓你的操作更消耗一些。

還有一個問題就是,如果你的非聚集索引中使用到了聚集索引的列,可能最造成一些不必要的性能消耗。我在網上查找了下一些資料,說的意思是:當你的非聚集索引使用到了聚集索引的列的時候,他會多進行一些不必要的聚集索引分頁的這樣的一個操作。從而效率的你的性能。

 

然後我們再看看,因爲在什麼時候去使用不同的索引。

首先:不要過度的去建立索引,過多的無用索引只會加重你的更新的速度,讓你的操作更加的遲緩。同時過多的索引頁不好進行管理,會讓的你的索引變得更加的混亂。大大加重後期的優化難度。

一般來說,我們在進行索引建立的時候需要用到一些工具。例如:Activity Monitor, Profiler

去不斷的分析你的系統使用最多的查詢的語句,以及在性能對你的系統造成堵塞的源頭,針對他進行相關的優化。

一般來說:

1.      主鍵,候選鍵和外鍵需要建立相關的索引。因爲他的連接查詢的可能性很高。

2.      頻繁檢索的列和按排序順序頻繁檢索的列。

 

但是針對頻繁操作的列,有些列也不同進行相關的索引

1.      列不同的值比較少。例如性別,狀態等。

2.      過長的值的列。例如:備註。

 

在刪除聚集索引之前,先刪除非聚集索引。如果你不按照這條方針做,則會導致無意義的重建非聚集索引。將表由聚集索引變爲堆會使得表上的非聚集索引重建,因爲非聚集索引的書籤由聚集索引鍵變爲RID。(摘抄)

 

考慮使用填充因子來減少頁分裂
         加入表中的數據已經達到了頁所能容納的最大值。那麼再插入數據就會導致頁分裂了。因此重建索引時可以使用填充因子,如果數據庫寫大於讀的話,設置填充因子爲75,如果讀寫大致相等的話,設置填充因子爲90到95。(這一點是我一直沒有注意的事情。)

填充因子是什麼呢?

盜用別人的解釋:

    在創建聚集索引和非聚集索引時,表中的數據按照索引列中的值的順序存儲在數據庫的數據頁中。在表中插入新的數據行或更改索引列中的值時, SQL Server 可能必須重新組織表中的數據存儲,以便爲新行騰出空間,保持數據的有序存儲。向一個已滿的索引頁添加某個新行時,SQL Server  把大約一半的行移到新頁中以便爲新行騰出空間。這種重組稱爲頁拆分。頁拆分會降低性能並使表中的數據存儲產生碎片。
    創建索引時,可以指定一個填充因子,以便在索引的每個葉級頁上留出額外的間隙和保留一定百分比的空間,供將來表的數據存儲容量進行擴充和減少頁拆分的可能性。填充因子的值是從 0  到 100  的百分比數值,指定在創建索引後對數據頁的填充比例。值爲 100  時表示頁將填滿,所留出的存儲空間量最小。只有當不會對數據進行更改時(例如,在只讀表中)纔會使用此設置。值越小則數據頁上的空閒空間越大,這樣可以減少在索引增長過程中對數據頁進行拆分的需要,但需要更多的存儲空間。當表中數據會發生更改時,這種設置更爲適當。提供填充因子選項是爲了對性能進行微調。但是,使用 sp_configure  系統存儲過程指定的服務器範圍的默認填充因子,在大多數情況下都是最佳的選擇。 

即使對於一個面向許多插入和更新操作的應用程序來說,數據庫讀取次數一般也超過數據庫寫入次數的 5  到 10  倍。因此,指定一個不同於默認設置的填充因子會降低數據庫的讀取性能,而降低量與填充因子設置值成反比。
只有當在表中根據現有數據創建新索引,並且可以精確預見將來會對這些數據進行哪些更改時,將填充因子選項設置爲另一個值纔有用。
填充因子只在創建索引時執行;索引創建後,當表中進行數據的添加、刪除或更新時,不會保持填充因子。如果試圖在數據頁上保持額外的空間,則將有背於使用填充因子的本意,因爲隨着數據的輸入,SQL Server 必須在每個頁上進行頁拆分,以保持填充因子指定的空閒空間百分比。因此,如果表中的數據進行了較大的變動,添加了新數據,可以填充數據頁的空閒空間。在這種情況下,可以重新創建索引,重新指定填充因子,以重新分佈數據。

歸根到底,填充因子的作用就是防止因爲數據的增加或者修改操作去進行不必要的重建索引頁這樣的操作,從而提高操作速度。

 

這篇文章可能和其他一些文章有部分雷同。因爲主要還是看了其他人的一些文章,從裏面提取出來的,再進行自己的理解的一些梳理。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章