日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【转载保存】B+树索引原理以及应用案例

發布時間:2024/8/23 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转载保存】B+树索引原理以及应用案例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

地址:https://www.jianshu.com/p/486a514b0ded

利用c/c++實現基于b+樹小型關系型數據庫:https://github.com/enpeizhao/duck_db

利用java實現的基于b+樹的數據庫案例:https://github.com/liumengjun/BPlusTreeIndex

1.什么是索引?

索引:加速查詢的數據結構。

2.索引常見數據結構:

#1.順序查找: 最基本的查詢算法-復雜度O(n),大數據量此算法效率糟糕。

#2.二叉樹查找(binary tree search): O(log2n)

?

圖1

左邊是數據表,一共有兩列七條記錄,最左邊的是數據記錄的物理地址(注意邏輯上相鄰的記錄在磁盤上也并不是一定物理相鄰的)。為了加快Col2的查找,可以維護一個右邊所示的二叉查找樹,每個節點分別包含索引鍵值和一個指向對應數據記錄物理地址的指針,這樣就可以運用二叉查找在O(log2n)O(log2n)的復雜度內獲取到相應數據。

#3.hash索引 無法滿足范圍查找。

#4.二叉樹、紅黑樹 [復雜度O(h)]導致樹高度非常高(平衡二叉樹一個節點只能有左子樹和右子樹),邏輯上很近的節點(父子)物理上可能很遠,無法利用局部性,IO次數多查找慢,效率低。todo 邏輯上相鄰節點沒法直接通過順序指針關聯,可能需要迭代回到上層節點重復向下遍歷找到對應節點,效率低

B-Tree 和 B+Tree數據結構:

#4.B-Tree:

結構:B-TREE 每個節點都是一個二元數組: [key, data],所有節點都可以存儲數據。key為索引key,data為除key之外的數據。結構如下:

?

圖2

檢索原理:首先從根節點進行二分查找,如果找到則返回對應節點的data,否則對相應區間的指針指向的節點遞歸進行查找,直到找到節點或未找到節點返回null指針。

缺點:1.插入刪除新的數據記錄會破壞B-Tree的性質,因此在插入刪除時,需要對樹進行一個分裂、合并、轉移等操作以保持B-Tree性質。造成IO操作頻繁。2.區間查找可能需要返回上層節點重復遍歷,IO操作繁瑣。

#5.B+Tree: B-Tree的變種

與B-Tree相比,B+Tree有以下不同點:非葉子節點不存儲data,只存儲索引key;只有葉子節點才存儲data。結構如下圖:

?

圖3

Mysql中B+Tree:在經典B+Tree的基礎上進行了優化,增加了順序訪問指針。在B+Tree的每個葉子節點增加一個指向相鄰葉子節點的指針,就形成了帶有順序訪問指針的B+Tree。這樣就提高了區間訪問性能:如果要查詢key為從18到49的所有數據記錄,當找到18后,只需順著節點和指針順序遍歷就可以一次性訪問到所有數據節點,極大提到了區間查詢效率(無需返回上層父節點重復遍歷查找減少IO操作)。

結構如下:

?

圖4

3.為什么Mysql選擇B+TREE索引? B+TREE索引有什么好處?

? 索引本身也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲的磁盤上。這樣的話,索引查找過程中就要產生磁盤I/O消耗,相對于內存存取,I/O存取的消耗要高幾個數量級,所以索引的結構組織要盡量減少查找過程中磁盤I/O的存取次數,提升索引效率。

磁盤存取原理:

索引一般以文件形式存儲在磁盤上,索引檢索需要磁盤I/O操作。與主存不同,磁盤I/O存在機械運動耗費,因此磁盤I/O的時間消耗是巨大的。

?

圖5

一個磁盤由大小相同且同軸的圓形盤片組成,磁盤可以轉動(各個磁盤必須同步轉動)。在磁盤的一側有磁頭支架,磁頭支架固定了一組磁頭,每個磁頭負責存取一個磁盤的內容。磁頭不能轉動,但是可以沿磁盤半徑方向運動(實際是斜切向運動),每個磁頭同一時刻也必須是同軸的,即從正上方向下看,所有磁頭任何時候都是重疊的(不過目前已經有多磁頭獨立技術,可不受此限制)。

磁盤結構:

?

圖6

磁道: 每個同心環叫做一個 扇區: 磁盤的最小存儲單元。 當需要從磁盤讀取數據時,系統會將數據邏輯地址傳給磁盤,磁盤的控制電路按照尋址邏輯將邏輯地址翻譯成物理地址,即確定要讀的數據在哪個磁道,哪個扇區。為了讀取這個扇區的數據,需要將磁頭放到這個扇區上方,為了實現這一點,磁頭需要移動對準相應磁道,這個過程叫做尋道,所耗費時間叫做尋道時間,然后磁盤旋轉將目標扇區旋轉到磁頭下,這個過程耗費的時間叫做旋轉時間。

局部性原理與磁盤預讀:

由于存儲介質的特性,磁盤本身存取就比主存慢很多,再加上機械運動耗費,磁盤的存取速度往往是主存的幾百分分之一,因此為了提高效率,要盡量減少磁盤I/O。為了達到這個目的,磁盤往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個字節,磁盤也會從這個位置開始,順序向后讀取一定長度的數據放入內存預讀可以提高I/O效率。預讀的長度一般為頁(page:計算機管理存儲器的邏輯塊-通常為4k)的整倍數. 主存和磁盤以頁為單位交換數據。當程序要讀取的數據不在主存中時,會觸發一個缺頁異常,此時系統會向磁盤發出讀盤信號,磁盤會找到數據的起始位置并向后連續讀取一頁或幾頁載入內存中。


B-/+Tree索引的性能優勢: 一般使用磁盤I/O次數評價索引優劣。

1.結合操作系統存儲結構優化處理: mysql巧妙運用操作系統存儲結構(一個節點分配到一個存儲頁中->盡量減少IO次數) & 磁盤預讀(緩存預讀->加速預讀馬上要用到的數據).

2.B+Tree 單個節點能放多個子節點相同IO次數,檢索出更多信息。

3.B+TREE 只在葉子節點存儲數據 & 所有葉子結點包含一個鏈指針 & 其他內層非葉子節點只存儲索引數據。只利用索引快速定位數據索引范圍,先定位索引再通過索引高效快速定位數據。

詳解:Mysql設計利用了磁盤預讀原理,將一個B+Tree節點大小設為一個頁大小,在新建節點時直接申請一個頁的空間,這樣就能保證一個節點物理上存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,這樣就實現了每個Node節點只需要一次I/O操作。

B-Tree索引、B+Tree索引: 單個節點能放多個子節點,查詢IO次數相同(mysql查詢IO次數最多3-5次-所以需要每個節點需要存儲很多數據)

B+TREE 只在葉子節點存儲數據 & 所有葉子結點包含一個鏈指針 & 其他內層非葉子節點只存儲索引數據。只利用索引快速定位數據索引范圍,先定位索引再通過索引高效快速定位數據。

B+Tree更適合外存索引,原因和內節點出度d有關。從上面分析可以看到,d越大索引的性能越好,而出度的上限取決于節點內key和data的大小:

B+Tree內節點去掉了data域,因此可以擁有更大的出度,擁有更好的性能。只利用索引快速定位數據索引范圍,先定位索引再通過索引高效快速定位數據。

dmax=floor(pagesize/(keysize+datasize+pointsize))


Mysql 索引實現-MyISAM & InnoDB: important

聚簇索引: 索引 和 數據文件為同一個文件。非聚簇索引: 索引 和 數據文件分開的索引。

MyISAM & InnoDB 都使用B+Tree索引結構。但是底層索引存儲不同,MyISAM 采用非聚簇索引,而InnoDB采用聚簇索引。?

MyISAM索引原理:采用非聚簇索引-MyISAM myi索引文件和myd數據文件分離,索引文件僅保存數據記錄的指針地址。葉子節點data域存儲指向數據記錄的指針地址。(底層存儲結構: frm -表定義、 myi -myisam索引、 myd-myisam數據)

MyISAM索引按照B+Tree搜索,如果指定的Key存在,則取出其data域的值,然后以data域值-數據指針地址去讀取相應數據記錄。輔助索引和主索引在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重復。MyISAM索引樹如下:

MyISAM非聚簇索引


InnoDB優勢:高擴展性,充分發揮硬件性能?Crash Safe、 支持事務、 可以在線熱備份

InnoDB特性:

1.?事務支持(ACID)2. 擴展性優良 3. 讀寫不沖突 4. 緩存加速

2. 功能組件: redo/undo & ?異步IO & ?MVCC & 行級別鎖 & Page Cache(LRU)

InnoDB物理存儲結構如下圖:

?

InnoDB表空間管理

InnoDB物理存儲文件結構說明:

? ? InnoDB以表空間Tablespace(idb文件)結構進行組織,每個Tablespace 包含多個Segment段,每個段(分為2種段:葉子節點Segment&非葉子節點Segment), 一個Segment段包含多個Extent,一個Extent占用1M空間包含64個Page(每個Page 16k),InnoDB B-Tree 一個邏輯節點就分配一個物理Page,一個節點一次IO操作。,一個Page里包含很多有序數據Row行數據,Row行數據中包含Filed屬性數據等信息。

? 表空間(ibd文件)

? 段(一個索引2段:葉子節點Segment & 非葉子節點Segment

? Extent(1MB):一個Extent(1M) 包含64個 Page(16k),一個Page里包含很多有序行數據 , InnoDB B-Tree 一個邏輯節點就分配一個物理Page,一個節點一次IO操作。

? Page(16KB)

? Row

? Field

表插入數據擴展原理: 一次擴張一個Extent空間(1M),64個Page,按照順序結構向每個page中插入順序。

InnoDB邏輯組織結構:

InnoDB索引樹結構

每個索引一個B+樹, 一個B+樹節點 = 一個物理Page(16K)

? 數據按16KB切片為Page 并編號, 編號可映射到物理文件偏移(16K * N), B+樹葉子節點前后形成雙向鏈表, 數據按主鍵索引聚簇, 二級索引葉節點存儲主鍵值, 通過葉節點主鍵值回表查找數據。

InnoDB索引原理:?

? 采用聚簇索引- InnoDB數據&索引文件為一個idb文件,表數據文件本身就是主索引,相鄰的索引臨近存儲。 葉節點data域保存了完整的數據記錄(數據[除主鍵id外其他列data]+主索引[索引key:表主鍵id])。 葉子節點直接存儲數據記錄,以主鍵id為key,葉子節點中直接存儲數據記錄。(底層存儲結構:?frm -表定義、 ibd: innoDB數據&索引文件)

注:由于InnoDB采用聚簇索引結構存儲,索引InnoDB的數據文件需要按照主鍵聚集,因此InnoDB要求表必須有主鍵(MyISAM可以沒有)。如果沒有指定mysql會自動選擇一個可以唯一表示數據記錄的列作為主鍵,如果不存在這樣的列,mysql自動為InnoDB表生成一個隱含字段(6個字節長整型)作為主鍵。 InnoDB的所有 輔助索引 都引用 數據記錄的主鍵 作為data域。

? 聚簇索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得數據記錄主鍵,然后用主鍵到主索引中檢索獲得數據記錄。InnoDB聚簇索引結構:

InnoDB聚簇索引

索引查找流程:

#1.索引精確查找: 確定定位條件, 找到根節點Page No, 根節點讀到內存, 逐層向下查找, 讀取葉子節點Page,通過 二分查找找到記錄或未命中。(select * from user_info where id = 23)

?

索引精確查找過程

#2.索引范圍查找:讀取根節點至內存, 確定索引定位條件id=18, 找到滿足條件第一個葉節點

, 順序掃描所有結果, 直到終止條件滿足id >=22 (select * from user_info where id >= 18 and id < 22)

?

索引范圍查找過程

#3.全表掃描:直接讀取葉節點頭結點, 順序掃描, 返回符合條件記錄, 到最終節點結束

(select * from user_info where name = 'abc')

?

全表掃描過程

#4.二級索引查找

?

二級索引查找過程

Create table table_x(int id primary key, varchar(64) name,key sec_index(name) )

? Select * from table_x where name = “d”;

通過二級索引查出對應主鍵,拿主鍵回表查主鍵索引得到數據, 二級索引可篩選掉大量無效記錄,提高效率

Innodb對索引的優化 Insert Buffer ?todo

Innodb Buffer Pool: todo

Innodb 異步IO框架:

Innodb ACID如何保證:

?原子性 redo + undo ? 一致性 redo ? 隔離性 鎖 + MVCC ? 持久性 redo

Innodb Redo日志:

Innodb 行級別鎖:

?



作者:kimze1107
鏈接:https://www.jianshu.com/p/486a514b0ded
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。

總結

以上是生活随笔為你收集整理的【转载保存】B+树索引原理以及应用案例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。