聊聊 Mysql 索引和 redis 跳錶

一、Redis中的跳錶

跳錶可以簡單理解就是給鏈表加索引,當結點數量多的時候,這種添加索引的方式,會使查詢效率提高的非常明顯。

在這裏插入圖片描述

跳錶這個動態數據結構,不僅支持查找操作,還支持動態的插入、刪除操作,而且插入、刪除操作的時間複雜度也是 ○(㏒n)。

對於單純的單鏈表,需要遍歷每個結點來找到插入的位置。但是對於跳錶來說,因爲其查找某個結點的時間複雜度是 ○(㏒n),所以這裏查找某個數據應該插入的位置,時間複雜度也是 ○(㏒n)。


二、數據庫中的 B 樹和 B + 樹

1.B 樹,每個節點都存儲 key 和 data,所有節點組成這棵樹,並且葉子節點指針爲 null,葉子結點不包含任何關鍵字信息。

2.B + 樹,所有的葉子結點中包含了全部關鍵字的信息,及指向含有這些關鍵字記錄的指針,且葉子結點本身依關鍵字的大小自小而大的順序鏈接,所有的非終端結點可以看成是索引部分,結點中僅含有其子樹根結點中最大(或最小)關鍵字。(而 B 樹的非終節點也包含需要查找的有效信息)

  • 非葉結點僅具有索引作用,跟記錄有關的信息均存放在葉結點中。

  • 樹的所有葉結點構成一個有序鏈表,可以按照關鍵碼排序的次序遍歷全部記錄。

3.B 和 B + 樹的區別在於,B + 樹的非葉子結點只包含導航信息,不包含實際的值,所有的葉子結點和相連的節點使用鏈表相連,便於區間查找和遍歷。

在這裏插入圖片描述

B+樹的優勢:

1.B + 的磁盤讀寫代價更低

  • B + 的內部結點並沒有指向關鍵字具體信息的指針。因此其內部結點相對 B 樹更小。如果把所有同一內部結點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多。數據存放的更加緊密,具有更好的空間局部性。一次性讀入內存中的需要查找的關鍵字也就越多。因此訪問葉子節點上關聯的數據也具有更好的緩存命中率。相對來說 IO 讀寫次數也就降低了。

2.B+tree 的查詢效率更加穩定

  • 由於非終結點並不是最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。所以任何關鍵字的查找必須走一條從根結點到葉子結點的路。所有關鍵字查詢的路徑長度相同,導致每一個數據的查詢效率相當。

3. 便於區間查找

  • B + 樹的葉子結點都是相鏈的,因此對整棵樹的便利只需要一次線性遍歷葉子結點即可。而且由於數據順序排列並且相連,所以便於區間查找和搜索。而 B 樹則需要進行每一層的遞歸遍歷。相鄰的元素可能在內存中不相鄰,所以緩存命中性沒有 B + 樹好。

Redis選中跳錶而不使用B+樹

redis 使用跳錶不用 B + 數的原因是:redis 是內存數據庫,而 B + 樹純粹是爲了 mysql 這種 IO 數據庫準備的。B + 樹的每個節點的數量都是一個 mysql 分區頁的大小

Redis 中的有序集合是通過跳錶來實現的,嚴格點講,還用到了散列表(關於散列表),如果查看 Redis 開發手冊,會發現 Redis 中的有序集合支持的核心操作主要有下面這幾個:

  • 插入一個數據
  • 刪除一個數據
  • 查找一個數據
  • 按照區間查找數據(比如查找在 [100,356] 之間的數據)
  • 迭代輸出有序序列

其中,插入、查找、刪除以及迭代輸出有序序列這幾個操作,紅黑樹也能完成,時間複雜度和跳錶是一樣的,但是,按照區間來查找數據這個操作,紅黑樹的效率沒有跳錶高。

對於按照區間查找數據這個操作,跳錶可以做到 ○(㏒n) 的時間複雜度定位區間的起點,然後在原始鏈表中順序往後遍歷就可以了。這樣做非常高效。

當然,還有其他原因,比如,跳錶代碼更容易實現,可讀性好不易出錯。跳錶更加靈活,可以通過改變索引構建策略,有效平衡執行效率和內存消耗


參考:https://www.cnblogs.com/aspirant/p/11475295.html

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