聚簇索引和聚簇索引介紹

聚簇索引和聚簇索引介紹

一.    什麼是索引和創建索引的好處

  • 什麼是索引

  在數據庫中,索引的含義與平常意義上的「索引」一詞並沒有多大區別,與書中的索引同樣,數據庫中的索引使您能夠快速找到表中的特定信息。索引包含從表中一個或多個列生成的鍵,以及映射到指定數據的存儲位置的指針,也就是說索引由鍵 指針組成。它是用於提升數據庫表數據訪問速度的數據庫對象。html

  • 創建索引的好處:

    • 索引能夠避免全表掃描。多數查詢能夠僅掃描少許索引頁及數據頁,而不是遍歷全部數據頁。
    • 對於非彙集索引,有些查詢甚至能夠不訪問數據頁。如字典的目錄就能夠查到全部拼音第一字母爲的全部字。
    •  彙集索引能夠避免數據插入操做集中於表的最後一個數據頁。
    •  一些狀況下,索引還可用於避免排序操做。

二.基礎知識

2.1 頁

   數據庫文件存儲是已頁爲存儲單元的,一個頁是8K(8192Byte),一個頁就能夠存放N行數據。咱們經常使用的頁類型就是數據頁和索引頁。一個頁中除了存放基本數據以外還須要存放一些其餘的數據,如頁的信息、偏移量等,以下圖所示。數據庫

   雖然SQLServer是以頁爲單位存儲數據,可是其分配空間是以一個盤區爲單位的(8個頁=64K),這樣作的目的主要是爲提升I/O的性能。緩存

 

一條索引記錄中包含的基本信息包括:鍵值 + 邏輯指針。網絡

SQLServer中使用頁爲存儲單元的,那麼在創建索引時,其索引節點就是頁了,而後樹的鍵值就是存放到這些頁(節點)中的。就是說表中的數據行就是存放到頁上的,一個表有多個頁構成,這些頁以樹的結構存放。架構

2.2 B樹

   B樹即二叉搜索樹,全部非葉子節點最低擁有兩個子節點,基本信息以下圖所示。都是小的元素放左邊,大的元素放右邊。好比說要查找某個元素,其時間複雜度就對應該元素的深度,如要查詢9,從根節點開始,只要比較三次就找到他了,其查詢效率是很是高的。數據庫設計

   子節點:最多兩個子節點(指針分別指向Left和Right)佈局

階數(節點子節點個數):2性能

深度:就是層數,各個葉子節點不必定同樣,如節點21的深度爲4,40的深度爲3測試

 

2.2 B-樹

B-樹是一中多路搜索樹,其階數能夠自定義(>2),是不少數據及文件系統應用的一種索引結構,基本特徵如:優化

1) 階數(M)>2,即孩子數量大於2個

2) 每一個結點存放至少M/2-1(取上整)和至多M-1個關鍵字;(至少2個關鍵字)

3) 非葉子結點上的多個關鍵字是按照順序排列的:K[1], K[2], …, K[M-1];且K[i] < K[i+1];

4) 全部葉子節點都位於同一層,所以葉子節點的深度都是同樣的

5) 非葉子結點的關鍵字個數=指向兒子的指針個數-1;

6) 非葉子結點的指針:P[1], P[2], …, P[M];其中P[1]指向關鍵字小於K[1]的子樹,P[M]指向關鍵字大於K[M-1]的子樹,其它P[i]指向關鍵字屬於(K[i-1], K[i])的子樹;

以下圖是一個三階的B-樹,節點[18]有兩個指針分別指向其2個子節點。

 

這時若是要插入一個值17,其處理步驟:

1) 從根節點進入,17小於22,進入左邊的節點[18];

2) [18]不是葉子節點,繼續向下搜索,17小於18,進入其左邊的子節點[12,16];

3) [12,16]爲葉子節點,插入到該節點;

4) 節點[12,16,17]元素大於2了(3階樹的節點關鍵字數量應>3/2-1,<3-1),所以該節點須要分裂,分裂中間的元素16到父節點18中去;

5) 12,17分裂成了兩個子節點了;

分裂後的效果以下圖

   以上圖片效果來自一個外國大學裏面的的在線版B-樹的測試,網站:http://www.cs.usfca.edu/~galles/visualization/BTree.html ,你們能夠去這個網站測試,效果很直觀,外國人就是牛。本人之前用C#+GDI實現過相似的效果,結果仍是能夠的,就是當樹太大的時候,佈局很差處理了。

 

2.3 B+樹

B+樹是B-樹的變體,也是一種多路搜索樹,一棵m 階的B+樹和m 階的B-樹的差別在於: 

l 非葉子節點的子節點和其關鍵字相同,即節點有三個元素(關鍵字),他就確定有三個子節點; 

l 非葉子節點的子節點P[i],指向關鍵字值屬於[K[i], K[i+1])的子樹(B-樹是開區間); 

l 全部葉子節點增長一個鏈指針; 

l 全部關鍵字的數據都在葉子節點中;

 以下圖所示,圖片來自網絡(http://www.cnblogs.com/chjw8016/archive/2011/03/08/1976891.html)。

 

三:什麼是彙集索引

3.1           彙集索引定義

彙集索引是根據數據行的鍵值在表中排序存儲數據行。索引定義中包含彙集索引列。每一個表只能有一個彙集索引。只有當表包含彙集索引時,表中的數據行才按排序順序存儲。若是表具備彙集索引,則該表稱爲彙集表。集索引決定了表數據的存儲順序,若是表沒有彙集索引,則其數據行存儲在一個稱爲堆的無序結構中。

3.2           彙集索引的結構

對於某個彙集索引,索引指向該彙集索引某個特定分區(數據頁)的頂部。SQL Server 將在索引中向下移動以查找與某個彙集索引鍵對應的行。緣由是彙集索引的索引順序就是數據排列順序。

 
  •  彙集索引與查詢操做

  • 如上圖,在創建彙集索引後,當須要在根據此字段查找特定的記錄時,數據庫系統會根據特定的系統表查找的此索引的根,而後根據指針查找下一個,直到找到。數據查詢時首先是對索引表查詢,若是此時索引表在緩存中能夠找到,則能夠避免一次IO操做。在索引表中找到所需數據索引值後,就能夠肯定目標數據行所在的數據位置,從而讀取數據。
  •  彙集索引與插入和刪除操做

  • 插入數據時,首先根據索引找到對應的數據頁,而後經過挪動已有的記錄爲新數據騰出空間,最後插入數據。
  • 刪除數據時將致使其下方的數據行向上移動以填充刪除記錄形成的空白。
  • 對於數據的刪除操做,可能致使索引頁中僅有一條記錄,這時,該記錄可能會被移至鄰近的索引頁中,原索引頁將被回收,即所謂的「索引合併」。一樣插入數據頁會更改索引。每一次索引更改都是一次IO操做。
  • 彙集索引的創建會下降數據插入和刪除的效率。

四.       什麼是非彙集索引

4.1           非彙集索引定義

非彙集索引並非在物理上排列數據,即索引中的邏輯順序並不等同於表中行的物理順序,索引是指向表中行的位置的指針,這些指針自己是有序的,經過這些指針能夠在表中快速定位數據。

 

4.2           非彙集索引的結構

因爲非彙集索引數據存儲時無序的,因此在非彙集索引中指針包含數據行在數據頁中的偏移量。即指針由 數據頁 + 數據行偏移量 組成。

 

  •  非彙集索引的查詢

  • 如上圖,在創建非彙集索引後,當須要在根據此字段查找特定的記錄時,數據庫系統會根據特定的系統表查找的此索引的根,而後根據指針查找,直到找到。數據查詢時首先是對索引表查詢,若是此時索引表在緩存中能夠找到,則能夠避免一次IO操做。在索引表中找到所需數據索引值後,就能夠肯定目標數據行所在的數據位置,從而讀取數據。
  • 非彙集索引的插入刪除

    •   若是一張表包含一個非彙集索引但沒有彙集索引,則新的數據將被插入到最末一個數據頁中,而後非彙集索引將被更新。若是也包含彙集索引,該彙集索引將被用於查找新行將要處於什麼位置,隨後,彙集索引、以及非彙集索引將被更新。

  若是在刪除命令的Where子句中包含的列上,建有非彙集索引,那麼該非彙集索引將被用於查找數據行的位置,數據刪除以後,位於索引葉子上的對應記錄也將被刪除。若是該表上有其它非彙集索引,則它們葉子結點上的相應數據也要刪除

 

 五。彙集索引和非彙集的區別

彙集索引和非彙集索引的根本區別是數據記錄的排列順序和索引的排列順序是否一致,彙集索引表記錄的排列順序與索引的排列順序一致,優勢是查詢速度快,由於一旦具備第一個索引值的紀錄被找到,具備連續索引值的記錄也必定物理的緊跟其後,從而縮小了搜索範圍,對於返回某一範圍的數據效果最好。

彙集索引的缺點是對錶進行修改速度較慢,這是爲了保持表中的記錄的物理順序與索引的順序一致,而把記錄插入到數據頁的相應位置,必須在數據頁中進行數據重排,下降了執行速度。
  非彙集索引指定了表中記錄的邏輯順序,數據記錄的物理順序和索引的順序不一致,彙集索引和非彙集索引都採用了B樹的結構,但非彙集索引的葉子層順序並不與實際的數據頁相同,而採用指向表中的記錄在數據頁中位置的方式。非彙集索引比彙集索引層次多,添加記錄不會引發數據順序的重組。在有大量不一樣數據的列上創建非彙集索引,能夠提升數據的查詢和修改速度。

在對彙集索引列查詢時,彙集索引的速度要比非彙集索引速度快。

在對彙集索引列排序時,彙集索引的速度要比非彙集索引速度快。可是若是數據量比較大時,如10萬以上,則兩者的速度差異不明顯。

 彙集索引和非彙集的創建原則

在建立索引時要作到三個適當,即在適當的表上、適當的列上建立適當數量的索引。雖然這能夠經過一句話來歸納優化的索引的基本準則,可是要作到這一點的話,須要作出很大的努力。具體的來講,要作到這個三個適當有以下幾個要求。

5.1           根據表的大小來建立索引。

雖然給表建立索引,能夠提升查詢的效率。可是須要注意的是,索引也須要必定的開銷的。爲此並非說給全部的表都建立索引,那麼就能夠提升數據庫的性能。這個認識是錯誤的。給全部的表都建立了索引,那麼其反而會給數據庫的性能形成負面的影響。由於此時濫用索引的開銷可能已經遠遠大於由此帶來的性能方面的收益。因此,數據庫管理員首先須要作到,爲合適的表來創建索引,而不是爲全部的表創建索引。

通常來講,不須要爲比較小的表建立索引。由於即便創建了索引,其性能也不會獲得很大的改善。相反索引創建的開銷,如維護成本等等,要比這個要大。也就是說,付出的要比獲得的多,顯然違反常理。

另外,就是對於超大的表,也不必定要創建索引。有些表雖然比較大,記錄數量很是的多。可是此時爲這個表創建索引並必定的合適。對於一些超大的表,創建索引有時候每每不可以達到預計的效果。並且在大表上創建索引,其索引的開銷要比普通的表大的多。那麼究竟是否給大表創建索引呢?主要是看兩個方面的內容。首先是須要關注一下,在這張大表中常常須要查詢的記錄數量。通常來講,若是常常須要查詢的數據不超過10%15%的話,那就沒有必要爲其創建索引的必要。由於此時創建索引的開銷可能要比性能的改善大的多。若是數據庫管理員須要得出一個比較精確的結論,那麼就須要進行測試分析。

5.2           根據列的特徵來建立索引

列的特色不一樣,索引建立的效果也不一樣。須要瞭解爲哪些列建立索引能夠起到事半功倍的效果。同時也須要了解爲哪些列建立索引反而起到的是事倍功半的效果。

索引設置的是否恰當,不只跟數據庫設計架構有關,並且還跟企業的經濟業務相關。雖然一開始已經作了索引的優化工做。可是隨着後來經濟數據的增長,這個索引的效果會愈來愈打折扣。因此須要隔一段時間,對數據庫的索引進行優化。該去掉的去掉,該調整的調整,以提升數據庫的性能。

 

5.3           在一個表上建立多少索引合適

一般來講,表的索引越多,其查詢的速度也就越快。可是,表的更新速度則會下降。這主要是由於表的更新同時也是索引的更新。到底在表中建立多少索引合適,就須要在這個更新速度與查詢速度之間取得一個均衡點。如對於一些數據倉庫或者決策型數據庫系統,其主要用來進行查詢。相關的記錄每每是在數據庫初始化的時候導入。此時,設置的索引多一點,能夠提升數據庫的查詢性能。同時由於記錄不怎麼更新,因此索引比較多的狀況下,也不會影響到更新的速度。相反,若是那些表中常常須要更新記錄,如一些事務型的應用系統,數據更新操做是屢見不鮮的事情。此時若是在一張表中創建過多的索引,則會影響到更新的速度。因爲更新操做比較頻繁,因此對其的負面影響,要比查詢效率提高要大的多。此時就須要限制索引的數量,只在一些必要的字段上創建索引。

總之,在適當的表、適當的列上創建適當的索引。具體的索引優化內容仍是須要在平常工做中繼續體會與總結。

下面的表總結了什麼時候使用匯集索引或非彙集索引:

動做描述

使用匯集索引

使用非彙集索引

列常常被分組排序

返回某範圍內的數據

不該

一個或極少不一樣值

不該

不該

小數目的不一樣值

不該

大數目的不一樣值

不該

頻繁更新的列

不該

外鍵列

主鍵列

頻繁修改索引列

不該

 注:具體參考數據庫\聚簇索引和非聚簇索引.ppt

相關文章
相關標籤/搜索