圖說數據庫索引

數據庫儲存結構

常見的數據庫儲存空間的基本結構是數據頁,一個數據頁的大小一般爲 16KB。數據頁的頭信息中,保留着前向指針和後向指針,分別指向前一頁和後一頁,數據頁之間形成了雙向鏈表。
在數據頁內部,存儲了用戶記錄(即使用數據庫插入的一條條記錄),記錄按照主鍵值大小升序排序。每條記錄都有一個後向指針,指向後一條記錄,因此記錄之間形成了單向鏈表。值得注意的是,數據頁還會自動增加兩條額外的記錄,分別爲最小記錄和最大記錄,規定最小記錄指向數據頁中主鍵值最小的記錄,數據頁中主鍵值最大的記錄指向最大記錄。
在這裏插入圖片描述

數據頁內的查找

  • 單頁查找
    可以注意到,每個數據頁內的主鍵都是有序的,如果需要查找某一個主鍵的值,可以使用二分法很快地定位到記錄。但是要查找非主鍵列的值,因爲非主鍵列並不是有序的,所以只能從最小記錄開始依次遍歷整頁,頁的記錄量很大,所以效率會很低。
  • 多頁查找
    多頁查找,需要先定位到頁,再定位到頁內的記錄。由於頁是無序的,所以要從第一頁開始,遍歷每一頁,在每一頁中使用上述的單頁查找方法,直到找到指定的記錄。

可以看出,上述的方案確實存在效率上的問題。一個比較好的方式是參照頁內主鍵快速定位的方法建立索引目錄頁。

索引的建立

在這裏插入圖片描述
在數據頁的上方,增加了目錄頁來方便定位頁碼。目錄頁至於兩列記錄,一列爲key,即它指向的數據頁的鍵值最小的記錄,另外一列爲它指向的數據頁的頁碼。這樣以來,就可以在上述多頁查詢的第一個步驟中,利用二分法快速定位到頁碼。而這些目錄頁該如何保存呢,我們可以把它當成一條條記錄,保持着單向關係,再存進一個數據頁中,數據頁間保持着雙向關係。如下圖所示:
在這裏插入圖片描述
現在我們擁有兩層的數據頁,再加一層呢,是不是越來越像樹啦?沒錯,它是一棵 B+ 樹。
在這裏插入圖片描述
用戶數據都被存放到最底層的節點上,即葉子節點上。而非葉子節點,則存放的索引,最上面的節點爲根節點。有了 B+ 樹以後,我們就可以很輕鬆地從根節點出發去定位到記錄的頁碼了。

索引的類型

  • 聚簇索引:以主鍵值爲排序依據的索引
  • 二級索引:以非主鍵值爲排序依據的索引
  • 聯合索引:以多個列爲排序依據的索引

其中,二級索引和聯合索引的葉子節點不會帶上完整的用戶記錄,而是隻會帶上主鍵,所以在經過二級索引和聯合索引的查找後,只能拿到主鍵值,而不能拿到完整記錄。如果要拿到完整記錄,就需要用主鍵值再到聚簇索引中用主鍵值查一遍,這個操作也叫做 “回表”。

之所以二級索引和聯合索引的葉子節點不帶上完整的用戶記錄,是因爲如果帶上完整的用戶記錄以後,相當於這個 B+ 樹把所有的用戶記錄都拷貝一遍,非常浪費空間。而每次我們建立二級索引或聯合索引的時候,都會新建一棵 B+ 樹。

索引的使用

索引在用於範圍匹配搜索、排序、分組的情況下,比較有用,仔細想想鍵值的有序性就可以知道了。
而說到這,就要說起業務代碼中需要用到多個字段不重複插入,就需要多個列作爲聯合索引唯一,在 greenDao 中的使用是這樣的

@Entity(
    indexes = {
       @Index(value = "column1,column2,column3", unique = true)
    }
)

在執行 insertorupdate 就可以滿足業務要求了。也可以使用 IGNORE 關鍵字或者ON DUPLICATE KEY UPDATE 來更新。

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