數據庫索引的原理

我們從盤古開天闢地講起

1、首先數據庫中的數據是以什麼樣的形式存儲在我們的設備中呢?

一個表是由幾個字段的數據組成,雖然我們看上去這些數據都有序地、“一行一行地”存在表中。但是事實上,物理存儲中的這些數據可能分散在不同的數據塊中。比如(id=1, name='martin',age=22,sex=1),要找到martin這個人的信息,在查找的時候先找到第一個數據(id=1)所在的數據庫地址,然後在這個數據的底端找到下一個數據塊的地址(name='martin'的地址),類似於鏈表的結構。如果我們查找的數據量比較大,顯然這種方法是不合適的。所以出現了索引,索引是對錶中的字段在另開闢的空間中建立一種新的數據結構(B/B+樹,有的數據庫也用哈希桶)保存這些值,對這些值進行排序,每個值又指向其相關的值。沒有索引的情況下,數據可能一整塊一整塊地存儲在磁盤上;但是加了索引之後,表在磁盤上的存儲結構就由整齊排列的結構轉變爲樹狀結構。

 

2、再講講B樹和B+樹

我們都知道二叉樹這個可以將查詢範圍每次縮小1/2的數據結構。儘管這個效率已經非常可觀,我們爲什麼還要用B樹和B+樹作爲數據庫索引的存儲結構呢?我們上邊說到,在沒有索引的情況下數據庫中的數據可能一塊一塊地存儲在硬盤上,而硬盤是順序存取設備,硬盤中需要磁頭先定位再存取,這就造成了就近讀取速度快一些。二叉樹在滿的情況下,每個節點僅有兩個孩子節點,這就容易造成節點兩端的深度不一致,可能某一端數據比較多,比較深。而我們查詢時需要先通過IO操作將數據加載到內存中,而數據不能一次性全部加載到內存中,只能逐一加載每個磁盤頁(對應樹的一個節點),二叉樹深度過大就會造成磁盤io操作頻繁效率低下,而B樹和B+樹這類平衡樹能保證節點兩邊樹的深度相同,並且每個節點能存儲多個元素,降低了深度,也就減少了IO操作。

(PS:1、MySQL底層是B+樹,Oracle是B樹,其他也有一些數據庫使用是哈希桶。2、磁盤適合B樹結構存儲,內存適合Hash存儲,因爲內存是隨機訪問隨機存儲的存儲設備,不需要磁頭定位)

 

3、索引具體存儲了啥?

上面說過索引是對錶中的某些字段在另開闢的空間中建立的一種新的數據結構。那麼索引有哪些數據組成呢?一條索引中包含的基本信息包括鍵值(即你定義索引時指定的所有字段的值)+邏輯指針(指向數據頁或者另一索引頁,索引頁就是存儲索引的空間)。索引頁中的數據量比真實數據小許多,也密集許多,所以在索引中查找時在io上佔很大優勢。

B樹的非葉子節點對應了索引頁,葉子節點對應了數據頁。

 

4、索引有哪些類型?

索引分爲聚集索引非聚集索引。比方說我們經常給表的id字段加上主鍵,主鍵就是一個聚集索引(當然,創建主鍵的時候可以聲明爲非聚集索引。主鍵必須依賴於索引,伴隨這所以的主鍵不能刪除,除非同時刪除主鍵。一個表也只能有一個聚集索引,因爲真實數據的物理存儲只可能是一種;如果一張表沒有索引,那麼它被稱爲堆集,這樣的表中數據行沒有特定的順序,所有的的新行都將被添加到末尾位置),它將整個表變成了一個索引,表中的所有數據就以平衡樹的形式存儲,所以一個表只能有一個主鍵。舉個例子,有一萬條數據,在沒有主鍵索引之前,最壞的情況可能需要一萬次IO操作、匹配才能查到結果,但是在B樹的情況下,只需要匹配樹的深度次數即可。當然,索引也有副作用。索引讓查詢速度上升,但是會讓寫入速度下降,因爲平衡多叉樹必須實時維持一個正確的姿態,增刪改都會影響這棵樹各節點的內容,破壞樹的結構。因此在每此改變數據時,樹的結構就需要改變,這個開銷不可避免。

而非聚集索引就是我們平時提起和使用的常規索引,也是採用平衡樹作爲索引的數據結構。每新建一個索引就會將表中的數據拷貝一份(對於主鍵這個聚集索引,索引和表數據是一起存儲的,並不會單獨拷貝一份作爲索引數據,不然也太蠢了),比方說我們給name字段加上索引,那麼這個索引僅有name字段的值構成。

聚集索引和非聚集索引的區別在於:1、聚集索引表數據按照索引的順序存儲,葉子節點存儲了真實的數據行,不再有另外單獨的數據頁;而非聚集索引表數據存儲順序與索引順序無關,葉節點包含了索引的字段值以及指向數據頁數據行的邏輯指針。2、通過聚集索引可以查找到我們需要查找的數據,而通過非聚集索引可以查找到記錄對應的主鍵值,再通過主鍵值來定位數據。可以這麼說:主鍵是通往真是數據的唯一途徑。但是有一種情況不需要通過主鍵定位,就是覆蓋索引。比方說我們給name和age加上索引,那麼執行 select age from table where name = 'martin' 的時候,由於age也在索引中,所以不需要再通過主鍵來定位了。

 

參考博客

https://www.cnblogs.com/aspwebchh/p/6652855.html

https://www.cnblogs.com/lj820403/p/7246657.html

https://kb.cnblogs.com/page/45712/

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