數據庫索引詳解
索引
當我們在設計數據庫的時候,對表的一些屬性有時會加上索引,但索引為什么能提高檢索速率呢?是不是用了索引就一定可以提高效率呢?不同索引之間有什么區別呢?搞懂這些問題是靈活運用索引的必備條件。接下來,我們將一 一進行討論。
一.索引的本質
索引也分為不同的種類,而且也有不同的分類方法,比較常用的是普通索引和聚集索引。
1.普通索引
其實對某字段建立了索引就相當於是對該字段新建立了一個表,這個表里的元素是安照這個字段有序排列。這樣有什么好處呢?好處就在於如果我們select的時候要搜索該字段,那就會在這個索引表中先查找,因為索引表是有序的,所以在檢索該字段的時候就是二分搜索,速度自然會比在原表上快,然后如果我只需要這一個字段的話,查詢就可以結束了,但如果還需要除索引字段的其他字段的話,那么就會根據這個索引表的字段對應到主表中,然后再獲取。
看了上面講的,是不是感覺有點迷茫?下面看一下圖就會清晰很多。

(圖片來源於百度)
大家可以看到這里我們以Col2建立索引之后右邊有一顆二叉樹,可能大家會問不是說好了是一張表嗎,怎么又是二叉樹了,好吧表本身就是一種樹形的數據結構存儲,雖然實際上很少會選取二叉樹,但此處方便講解。可以看到Col2單獨的一棵樹,然后每一個節點對過來是一條記錄,如果我們執行 select Col2 from tablename where Col2=34;那么直接在右邊的樹中二叉搜索,找到了就可以返回了。如果我們執行 select * from tablename where Col2=34;那么可以看到需要的不僅僅是Col2這一個字段,那么還是先在二叉樹中查找,然后找到了之后對應到主表中,然后返回整條記錄。
1.索引的數據結構
通過上面的圖我們可以看到,索引的本質其實就是新建了一張表,而表本質上的數據結構就是樹形結構,所以索引也是樹形結構。但實際運用中並沒有誰用紅黑樹,avl樹這種數據結構,一般是b+樹,接下來給大家大致介紹一下b+樹的構成。

(圖片來源於百度)
b+樹在構建時和我們之前提到的二三樹很像,只是有一些改進,b+樹的非葉子節點不包含value的信息,也就是說非葉子結點只起到一個導航的作用,所有的value放在了葉子結點里,這樣由於B+樹在內部節點上不包含數據信息,因此在內存頁中能夠存放更多的key。 數據存放的更加緊密,具有更好的空間局部性。因此訪問葉子節點上關聯的數據也具有更好的緩存命中率。通常會將b+樹進行優化,增加順序訪問指針。

(圖片來源於百度0)
在B+Tree的每個葉子節點增加一個指向相鄰葉子節點的指針,就形成了帶有順序訪問指針的B+Tree。做這個優化的目的是為了提高區間訪問的性能,例如圖中如果要查詢key為從18到49的所有數據記錄,當找到18后,只需順着節點和指針順序遍歷就可以一次性訪問到所有數據節點,極大提到了區間查詢效率。
可以看到b+樹對於表的存儲是一種很方便的數據結構。那么為什么不用紅黑樹呢,因為數據量大的時候,會導致這種二叉樹深度太深,io次數會很多,層數很少的b+樹可以有效降低io次數。
聚集索引
聚集索引和普通索引是不一樣的,聚集索引是指數據庫表行中數據的物理順序與鍵值的邏輯(索引)順序相同。一個表只能有一個聚集索引,因為一個表的物理順序只有一種情況。意思就是說上面的普通索引我們可以看到是另建了一個表,然后當查詢到了索引沒有覆蓋到的字段的時候是將這個字段映射到了主表中然后進行查詢的。而聚集索引建立后主表本身就會按照這個索引的結構來存儲,意思就是說主表直接就按這個來存了。這也是為什么聚集索引一定是唯一的原因,因為一張表中只能有一種存儲方式。
聚集索引與普通索引
兩種索引誰更快呢?這當然是沒有懸念的,聚集索引更快咯,因為普通索引查到沒有覆蓋的字段的時候需要向主表中映射過去,然后再獲取,而聚集索引因為其本身就包含了所有數據,所以一次就好~
主鍵與聚集索引
在我們新建一個表時,如果沒有定義主鍵,那么表格的數據是順序線性存儲的,在定義的主鍵之后,因為主鍵默認有索引,並且在很多平台上默認是聚集索引,所以在主鍵定義的時候就會把整個表變為一個樹形結構(如果主鍵是聚集索引),但要知道的是主鍵不一定是聚集索引,也可以是普通索引,只是很多平台默認為聚集,不要盲目划等號。
索引的利弊
那么索引既然這么快是不是越多越好呢?不存在的,因為索引本身是一個數據表,那么在插入或刪除的時候就涉及到了索引表的改變,b+樹的插入刪除涉及到很多節點操作,或許會消耗很多時間。所以我們對於常改變的字段不宜建索引,而對於改動較少的字段就很合適,在設計表的時候我們要靈活選取,才能高效。
