色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Mysql索引為什么使用B+樹?

dyquk4xk2p3d ? 來源:良許Linu ? 2023-06-08 16:34 ? 次閱讀

		

		


		


		

		


		

		

		

		

		

		

在我們的印象中,mysql數據表里無非就是存儲一行行的數據。跟個excel似的。

直接遍歷這一行行數據,性能就是O(n),比較慢。為了加速查詢,使用了B+樹來做索引,將查詢性能優化到了O(lg(n))

但問題就來了,查詢數據性能在 lg(n) 級別的數據結構有很多,比如redis的zset里用到的跳表,也是lg(n),并且實現還賊簡單。

那為什么mysql的索引,不使用跳表呢?

我們今天就來聊聊這個話題

B+樹的結構

在這里,為了混點字數,我簡單總結下B+樹的結構。

d631e2a8-05d6-11ee-962d-dac502259ad0.pngB+樹查詢過程

如上圖,一般B+樹是由多個頁組成的多層級結構,每個頁16Kb,對于主鍵索引來說,最末級的葉子結點放行數據,非葉子結點放的則是索引信息(主鍵id和頁號),用于加速查詢。

比方說我們想要查找行數據5。會先從頂層頁的record們入手。record里包含了主鍵id和頁號(頁地址)。關注黃色的箭頭,向左最小id是1,向右最小id是7。那id=5的數據如果存在,那必定在左邊箭頭。于是順著的record的頁地址就到了6號數據頁里,再判斷id=5>4,所以肯定在右邊的數據頁里,于是加載105號數據頁。

105號數據頁里,雖然有多行數據,但也不是挨個遍歷的,數據頁內還有個頁目錄的信息,它可以通過二分查找的方式加速查詢行數據,于是找到id=5的數據行,完成查詢。

從上面可以看出,B+樹利用了空間換時間的方式(構造了一批非葉子結點用于存放索引信息),將查詢時間復雜度從O(n)優化為O(lg(n))

跳表的結構

看完B+樹,我們再來看下跳表是怎么來的。

同樣的,還是為了存儲一行行的數據。

我們可以將它們用鏈表串起來。

d6591fe4-05d6-11ee-962d-dac502259ad0.png單鏈表

想要查詢鏈表中的其中一個結點,時間復雜度是O(n),這誰頂得住,于是將部分鏈表結點提出來,再構建出一個新的鏈表。

d6609a8a-05d6-11ee-962d-dac502259ad0.png兩層跳表

這樣當我想要查詢一個數據的時候,我先查上層的鏈表,就很容易知道數據落在哪個范圍,然后跳到下一個層級里進行查詢。這樣就把搜索范圍一下子縮小了一大半。

比如查詢id=10的數據,我們先在上層遍歷,依次判斷1,6,12,很快就可以判斷出10在6到12之間,然后往下一跳,就可以在遍歷6,7,8,9,10之后,確定id=10的位置。直接將查詢范圍從原來的1到10,變成現在的1,6,7,8,9,10,算是砍半了。

d67fc1da-05d6-11ee-962d-dac502259ad0.png兩層跳表查找id為10的數據

既然兩層鏈表就直接將查詢范圍砍半了,那我多加幾層,豈不妙哉?

于是跳表就這樣變成了多層。

d69d5f10-05d6-11ee-962d-dac502259ad0.png三層跳表

如果還是查詢id=10的數據,就只需要查詢1,6,9,10就能找到,比兩層的時候更快一些。

d6b84af0-05d6-11ee-962d-dac502259ad0.png三層跳表查詢id為10的數據

可以看出,跳表也是通過犧牲空間換取時間的方式提升查詢性能。時間復雜度都是lg(n)

B+樹和跳表的區別

從上面可以看到,B+樹和跳表的最下面一層,都包含了所有的數據,且都是順序的,適合用于范圍查詢。往上的層級都是構建出來用于提升搜索性能的。這兩者實在是太像了。但他們兩者在新增和刪除數據時,還是有些區別的。下面我們以新增數據為例聊一下。

B+樹新增數據會怎么樣

B+樹本質上是一種多叉平衡二叉樹。關鍵在于"平衡"這兩個字,對于多叉樹結構來說,它的含義是子樹們的高度層級盡量一致(一般最多差一個層級),這樣在搜索的時候,不管是到哪個子樹分支,搜索次數都差不了太多。

當數據庫表不斷插入新的數據時,為了維持B+樹的平衡,B+樹會不斷分裂調整數據頁。

我們知道B+樹分為葉子結點和非葉子結點

當插入一條數據時,葉子結點和它上層的索引結點(非葉子結點)最大容量都是16k,它們都有可能會滿。

為了簡化問題,我們假設一個數據頁只能放三條行數據或索引。

加入一條數據,根據數據頁會不會滿,分為三種情況。

  • 葉子結點和索引結點都沒滿。這種情況最簡單,直接插入到葉子結點中就好了。

d6c62774-05d6-11ee-962d-dac502259ad0.png葉子和非葉子都未滿
  • 葉子結點滿了,但索引結點沒滿。此時需要拆分葉子結點,同時索引結點要增加新的索引信息。

d6dc9d56-05d6-11ee-962d-dac502259ad0.png葉子滿了但非葉子未滿.drawio
  • 葉子結點滿了,且索引結點也滿了。葉子和索引結點都要拆分,同時往上還要再加一層索引。

d6f9eb7c-05d6-11ee-962d-dac502259ad0.png葉子和非葉子都滿了

從上面可以看到,只有在葉子和索引結點都滿了的情況下,B+樹才會考慮加入一層新的結點。

要把三層B+樹塞滿,那大概需要2kw左右的數據。

跳表新增數據

跳表同樣也是很多層,新增一個數據時,最底層的鏈表需要插入數據。

此時,是否需要在上面的幾層中加入數據做索引呢?

這個就純靠隨機函數了。

理論上為了達到二分的效果,每一層的結點數需要是下一層結點數的二分之一。

也就是說現在有一個新的數據插入了,它有50%的概率需要在第二層加入索引,有25%的概率需要在第三層加個索引,以此類推,直到最頂層

舉個例子,如果跳表中插入數據id=6,且隨機函數返回第三層(有25%的概率),那就需要在跳表的最底層到第三層都插入數據。

d717f810-05d6-11ee-962d-dac502259ad0.png跳表插入數據

如果這個隨機函數設計成上面這樣,當數據量樣本足夠大的時候,數據的分布就符合我們理想中的"二分"。

跟上面B+樹不一樣,跳表是否新增層數,純粹靠隨機函數,根本不關心前后上下結點。

好了,基礎科普也結束了,我們可以進入正題了。

Mysql的索引為什么使用B+樹而不使用跳表?

B+樹是多叉樹結構,每個結點都是一個16k的數據頁,能存放較多索引信息,所以扇出很高三層左右就可以存儲2kw左右的數據(知道結論就行,想知道原因可以看之前的文章)。也就是說查詢一次數據,如果這些數據頁都在磁盤里,那么最多需要查詢三次磁盤IO

跳表是鏈表結構,一條數據一個結點,如果最底層要存放2kw數據,且每次查詢都要能達到二分查找的效果,2kw大概在2的24次方左右,所以,跳表大概高度在24層左右。最壞情況下,這24層數據會分散在不同的數據頁里,也即是查一次數據會經歷24次磁盤IO

因此存放同樣量級的數據,B+樹的高度比跳表的要少,如果放在mysql數據庫上來說,就是磁盤IO次數更少,因此B+樹查詢更快

而針對寫操作,B+樹需要拆分合并索引數據頁,跳表則獨立插入,并根據隨機函數確定層數,沒有旋轉和維持平衡的開銷,因此跳表的寫入性能會比B+樹要好。

其實,mysql的存儲引擎是可以換的,以前是myisam,后來才有的innodb,它們底層索引用的都是B+樹。也就是說,你完全可以造一個索引為跳表的存儲引擎裝到mysql里。事實上,facebook造了個rocksDB的存儲引擎,里面就用了跳表。直接說結論,它的寫入性能確實是比innodb要好,但讀性能確實比innodb要差不少。

redis為什么使用跳表而不使用B+樹或二叉樹呢?

redis支持多種數據結構,里面有個有序集合,也叫ZSET。內部實現就是跳表。那為什么要用跳表而不用B+樹等結構呢?

這個幾乎每次面試都要被問一下。

雖然已經很熟了,但每次都要裝作之前沒想過,現場思考一下才知道答案。

真的,很考驗演技。

大家知道,redis 是純純的內存數據庫。

進行讀寫數據都是操作內存,跟磁盤沒啥關系,因此也不存在磁盤IO了,所以層高就不再是跳表的劣勢了。

并且前面也提到B+樹是有一系列合并拆分操作的,換成紅黑樹或者其他AVL樹的話也是各種旋轉,目的也是為了保持樹的平衡

而跳表插入數據時,只需要隨機一下,就知道自己要不要往上加索引,根本不用考慮前后結點的感受,也就少了旋轉平衡的開銷

因此,redis選了跳表,而不是B+樹。

總結

  • B+樹是多叉平衡搜索樹,扇出高,只需要3層左右就能存放2kw左右的數據,同樣情況下跳表則需要24層左右,假設層高對應磁盤IO,那么B+樹的讀性能會比跳表要好,因此mysql選了B+樹做索引。

  • redis的讀寫全在內存里進行操作,不涉及磁盤IO,同時跳表實現簡單,相比B+樹、AVL樹、少了旋轉樹結構的開銷,因此redis使用跳表來實現ZSET,而不是樹結構。

  • 存儲引擎RocksDB內部使用了跳表,對比使用B+樹的innodb,雖然寫性能更好,但讀性能屬實差了些。在讀多寫少的場景下,B+樹依舊YYDS。


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 數據
    +關注

    關注

    8

    文章

    7048

    瀏覽量

    89073
  • MySQL
    +關注

    關注

    1

    文章

    813

    瀏覽量

    26594
  • 索引
    +關注

    關注

    0

    文章

    59

    瀏覽量

    10478

原文標題:Mysql索引為什么使用B+樹?

文章出處:【微信號:良許Linux,微信公眾號:良許Linux】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    mysql索引使用技巧有哪些?

    mysql索引使用技巧
    發表于 05-20 06:09

    MySQL索引使用優化和規范

    MySQL - 索引使用優化和規范
    發表于 06-15 16:01

    MySQL數據庫索引的底層是怎么實現的

    ' 。就能查出特定列(姓名列)的特定值(張三)的記錄。另外,它是一種數據結構。那么mysql的數據結構,采用的是B+。那么,為啥選B+
    發表于 07-28 15:30

    基于B+的動態數據持有性證明方案

    針對云存儲環境下的數據持有性證明( PDP)方案效率較低、不能很好支持全動態更新的問題,設計了一種基于B+的動態數據持有性證明方案。該方案引入雙線性對技術和數據版本表,支持用戶進行數據塊級的細粒度
    發表于 11-30 17:14 ?0次下載
    基于<b class='flag-5'>B+</b><b class='flag-5'>樹</b>的動態數據持有性證明方案

    基于KD和R的多維索引結構

    針對云存儲系統大多基于鍵值對 key,value模型存儲數據,多維查詢需要對整個數據集進行完全掃描,查詢效率較低的問題,提出了一種基于KD和R的多維索引結構(簡稱KD-R索引)。K
    發表于 01-25 15:13 ?0次下載
    基于KD<b class='flag-5'>樹</b>和R<b class='flag-5'>樹</b>的多維<b class='flag-5'>索引</b>結構

    MySQL索引使用原則

    一般來說, MySQL 中的 B-Tree 索引的物理文件大多都是以 Balance Tree 的結構來存儲的,也就是所有實際需要的數據都存放于 Tree 的 Leaf Node(葉子節點) ,而且
    的頭像 發表于 02-11 15:17 ?2724次閱讀
    <b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>使用原則

    MySQL索引的使用問題

    一、前言 在MySQL中進行SQL優化的時候,經常會在一些情況下,對MySQL能否利用索引有一些迷惑。譬如:1、MySQL 在遇到范圍查詢條件的時候就停止匹配了,那么到底是哪些范圍條件
    的頭像 發表于 01-06 16:13 ?1615次閱讀

    關于MySQL ORDER BY的詳解

    回答一些常見的問題(下文僅討論InnoDB存儲引擎)。 2 索引掃描排序和文件排序(filesort)簡介 我們知道InnoDB存儲引擎以B+作為索引的底層實現,
    的頭像 發表于 02-08 11:20 ?2479次閱讀
    關于<b class='flag-5'>MySQL</b> ORDER BY的詳解

    掌握這幾種方法 你的接口查詢速度將飛速提升

    很大時,大多慢查詢可以用索引解決,大多慢查詢也因為索引不合理而產生。 MySQL 索引基于 B+
    的頭像 發表于 07-06 14:38 ?1829次閱讀

    B+ 索引MySQL 中的認識

    概述 本質:數據庫維護某種數據結構以某種方式引用(指向)數據 索引取舍原則:索引的結構組織要盡量減少查找過程中磁盤I/O的存取次數 B 滿足的條件 d為大于1的一個正整數,稱為
    的頭像 發表于 11-08 11:11 ?1271次閱讀
    對 <b class='flag-5'>B+</b> <b class='flag-5'>樹</b>與<b class='flag-5'>索引</b>在 <b class='flag-5'>MySQL</b> 中的認識

    MySQL高級進階:索引優化

    MySQL官方對于索引的定義:索引是幫助MySQL高效獲取數據的數據結構。
    的頭像 發表于 06-11 11:13 ?582次閱讀
    <b class='flag-5'>MySQL</b>高級進階:<b class='flag-5'>索引</b>優化

    MySQL為什么選擇B+作為索引結構?

    MySQL中,無論是Innodb還是MyIsam,都使用了B+索引結構(這里不考慮hash等其他索引)。本文將從最普通的二叉查找
    的頭像 發表于 07-20 11:28 ?956次閱讀
    <b class='flag-5'>MySQL</b>為什么選擇<b class='flag-5'>B+</b><b class='flag-5'>樹</b>作為<b class='flag-5'>索引</b>結構?

    MySQL索引的常用知識點

    索引結構:B+ 索引其實是一種數據結構 注意B+MyS
    的頭像 發表于 09-30 16:43 ?468次閱讀

    索引是什么意思 優缺點有哪些

    的數據結構,以協助快速查詢、更新數據庫表中數據。索引的實現通常使用B及其變種B+。更通俗的說,索引
    的頭像 發表于 10-09 10:19 ?2963次閱讀

    一文了解MySQL索引機制

    的呢?一起靜下心來,耐心看完這篇文章吧,干貨不啰嗦,相信你一定會有所收獲。 一、索引模型 模型也就是數據結構,常見的三種模型分別是哈希表、有序數組和搜索。 了解MySQL的朋友已經知道,現在
    的頭像 發表于 07-25 14:05 ?299次閱讀
    一文了解<b class='flag-5'>MySQL</b><b class='flag-5'>索引</b>機制
    主站蜘蛛池模板: 午夜免费福利片| 国产精品资源在线观看网站| 菠萝菠萝蜜视频在线看1| 黄页网址大全免费观看| 色久久久综合88一本道| china男士同性视频tv| 久久一级片| 伊人青青青| 狠狠躁日日躁人人爽| 亚洲.日韩.欧美另类| 国产成人久久婷婷精品流白浆| 人成午夜免费视频| 啊片色播电影| 色多多污网站在线观看| 成人在线小视频| 天堂网久久| 国产嫩草影院精品免费网址| 午夜伦理:伦理片| 国产热久久精| 亚洲片在线观看| 久久九九日本韩国精品| 中国xxxxxz| 男gv纯肉免费视频| chinesedaddy80老年人| 三级黄色高清视频| 国产精品一区二区欧美视频| 亚洲国产成人99精品激情在线| 国语对白刺激真实精品| 一本道色综合手机久久| 老熟风间由美AV在线一区二区| 99国产精品偷窥熟女精品视频| 欧美s00老人| 国产a级午夜毛片| 亚洲精品一线二线三线无人区 | 亚洲国产剧情中文视频在线| 国自产精品手机在线视频| 曰批国产精品视频免费观看| 嫩草影院永久在线一二三四| 丰满的大白屁股ass| 亚洲青青草原| 欧美久久综合性欧美|