資源參考:mysql 實戰 45 講
Mysql 索引
- 索引的概念
- 索引的數據模型
- InnoDB 中的索引
索引的概念
索引,是爲了提高數據庫查詢效率的產物。它可以由多種 數據結構
實現
索引常見的數據模型
哈希表
哈希表是一種以 key - value
鍵值對存儲的數據結構,通過輸入 key 找到其對應的 value 值。
- 優點:
- 因爲
數據無序
,新增的時候不需要維護有序性,所以直接在尾部追加
數據即可。新增
數據的時間複雜度是 O(1)
- 一個 key 對應一個 value ,在 hash 值不重複的情況下,根據 key
查詢
對應 value 的時間複雜度爲 O(1)
- 因爲
- 缺點:
- 因爲數據是無序的,如果做
區間查詢
,key => [x, y] 的查詢,只能全部掃描一遍。時間複雜度爲 O(n)
- 因爲數據是無序的,如果做
所以哈希表常常適用於 等值查詢 的場景,類似 memcached, redis
有序數組
有序數組,顧名思義,用數組存儲一組數據,數據是按照某個值順序排列的(遞增或遞減),是有序的。
- 優點:
- 有序數組非常適合查詢。在等值查詢的場景下,因爲數據的有序性,簡單的,用
二分查找
即可找到需要的數據,時間複雜度爲 O(logn)
;在區間查詢
的場景下,先用二分法找到區間中較小的數據,再遍歷向右查詢,直到找到第一個大於右區間的值爲止。平均時間複雜度爲 O(nlogn)
- 有序數組非常適合查詢。在等值查詢的場景下,因爲數據的有序性,簡單的,用
- 缺點:
- 爲了維持數據的有序性,在插入數據之後,可能會對數據進行
搬移操作
。平均情況時間複雜度爲 O(n)
- 如果在
指定位置插入
數據,那麼其後的節點全部需要搬移。平均情況時間複雜度爲 O(n)
- 爲了維持數據的有序性,在插入數據之後,可能會對數據進行
所以有序數組,常常用來存儲一些 靜態數據
存儲。上月銷售量,銷售額等。
搜索樹
二叉搜索樹
每個父節點只有兩個子節點的書結構被成爲二叉數,其 左子樹小於父節點
,父節點小於右子樹
- 優點:
- 二叉搜索樹
搜索
節點的時間複雜度爲 O(logn)
- 爲了保證搜索的效率,所以需要保證是一顆
平衡二叉樹
,更新
時候的時間複雜度也爲O(logn)
- 二叉搜索樹
- 缺點:對於數據存儲系統而言,數據是寫到磁盤上的,在查詢的時候,需要儘量避免對磁盤的讀寫次數,這樣才能達到效率最優化。
由於二叉樹
葉子節點個數的限制
,如果作爲數據庫索引的數據結構,那麼 100 節點的二叉樹的樹高就會是 20,也就是說,一次搜索,可能
需要訪問到 20 個磁盤的數據快,這樣的效率是很低的
N 叉搜索樹
N 叉樹是基於二叉樹的基礎上衍生出來的針對數據庫系統高效的查詢數據結構。N 的值取決於數據快的大小。在 InnoDB 中,一個整型索引的 N 差不多是 1200,也就是說,一個父節點可以存放 1200 個子節點。一個樹高爲 4 的 N 叉數,差不多能存儲 17 億行整型索引,極大地減少了對於磁盤的隨機讀取,進而提升了查詢性能。
InnoDB 索引模型
InnoDB 的索引是基於 N 叉樹設計的一種數據結構,叫 B+ Tree。在 InnoDB 中,表數據存儲的邏輯結構,都是根據 主鍵順序
以 索引
的形式存放,被成爲 索引組織表
。
故每一個索引在 InnoDB 中,都對應一顆 B+ Tree。
主鍵索引和非主鍵索引
根據 B+ Tree 葉子節點的內容不同,索引類型被分爲了 主鍵索引
和 非主鍵索引
。
一般地,InnoDB 引擎中的數據表,在指定主鍵的情況下,Mysql 會根據指定的列創建對應的索引樹,而節點中的內容,是存放的整行數據。在 InnoDB 中,主鍵索引也被稱爲 聚簇索引
。
非主鍵字段上建立的索引,葉子節點中存放的是 主鍵
的值。在 InnoDB 中,非主鍵索引也被稱爲二級索引。
主鍵索引和非主鍵索引查詢的差別:
- 基於主鍵索引的查詢,搜索主鍵所在的 B+ Tree 即可直接拿到所需要的行數據
- 基於非主鍵索引的查詢,搜索全部行數據需要拿到主鍵 ID 後
回表
主鍵索引樹,拿到對應的數據
主鍵索引查詢會比非主鍵索引查詢少一次 回表
的操作,所以性能上更優,儘量在使用中使用主鍵查詢。