數據結構-各類樹的簡單理解mysql
理解:二叉樹的查找的優化,也是利用了相似二分查找的思想,讓查找的時間複雜度變成O(log2 n)算法
1. 樹sql
N叉樹浪費連接的存儲空間,N越大浪費越嚴重數據庫
解決:N等於2時連接空間浪費率最低,因而有了二叉樹數組
2. 二叉樹數據結構
優勢:連接空間浪費率達到最低。性能
缺點:無約束的二叉樹是無序的,查找的時間複雜度爲O(N),優化
解決:有了二叉搜索樹BST(Binary Search Tree)(又稱排序二叉樹、有序二叉樹、二叉查找樹)spa
3. 二叉搜索樹BST設計
優勢:排序二叉樹查詢、刪除和插入的平均時間複雜度都是O(log2 n)
缺點:可是隨着節點的添加和刪除,查詢的時間複雜度在O(log2 n) 到O(n)之間,
也就是說極端狀況可能成爲鏈表結構,查詢時間複雜度變成O(n)
解決:在添加和刪除節點時要維持二叉樹的平衡 -> 平衡二叉樹(AVL樹)、紅黑樹等
場景:實際使用很少
4. 平衡二叉樹(AVL樹)
優勢:AVL樹是高度平衡的二叉樹,查找效率很是高,接近二分查找。
缺點:每次插入和刪除都須要維護平衡,代價高,耗時大。
解決:不維持嚴格平衡,只保證近似平衡 -> 紅黑樹
場景:實際使用很少
5. 近似平衡的二叉樹-紅黑樹
優勢:性能穩定,插入、刪除、查找的複雜度在最好、最壞的狀況都是O(log2 n) ,性能略微遜色AVL樹。
實際中使用的比較多的。
缺點:比較適合數據所有加載到內存中。可是數據量大到大量數據在磁盤,須要屢次加載到磁盤中,每一個節點的訪問都要通過一次磁盤I/O, 效率是很是低下的。
解決:爲了減小減小磁盤IO,減小樹的高度,使樹變得「矮胖」(多叉樹)-> B樹和B+樹
數據庫索引多使用 B樹和B+樹
應用場景:使用比較多
JAVA8 HashMap的底層實現,數組+ 鏈表/紅黑樹
其中元素個數小於8時是鏈表,元素個數大於8時是紅黑樹;若是已是紅黑樹,元素個數減爲6(不是8的緣由:避免頻繁轉換)時退化爲鏈表。
6. B樹(又稱B-tree樹或B-樹)
優勢:減小I/O次數,多路查找樹,B樹在提升了磁盤IO性能
B-樹查詢時間複雜度不固定,與 key 在樹中的位置有關,最好爲O(1)
缺點:沒有解決元素遍歷的效率低下的問題,不利於遍歷和範圍查找。
解決:全部數據放在葉子節點節點上,組成一個雙向鏈表,非葉子節點存儲主鍵索引 -> B+樹
場景:MongoDB默認存儲引擎使用了B樹。
說明:讀多寫少且對遍歷數據的需求不強,B 樹與 LSM 樹在該場景下相比B+樹有更大的優點
7. B+樹:B樹的改進版
優勢:只有葉節點會存儲數據
場景:MySQL的InnoDB存儲引擎使用了B+樹
注意:B樹和B+樹的查詢效率確定不如紅黑樹,可是紅黑樹內存中才有優點。
8. B*樹:B+樹的改進版
9. 跳錶:
鏈表加多級索引的結構
能夠當作是鏈表實現二分查找,基於範圍查詢比紅黑樹效率高。
理論上通過改造後能夠代替B+樹成爲數據庫存儲索引設計。
10. LSM樹
不管是 B 樹仍是 B+ 樹,向這些數據結構組成的索引文件中寫入記錄都須要執行的磁盤隨機寫。
LSM 樹的優化邏輯就是犧牲部分的讀性能,將隨機寫轉換成順序寫以優化數據的寫入。
a.在不限制寫入的狀況下;
LSM 樹的寫入性能是 B 樹的 1.5 ~ 2 倍;
LSM 樹的讀取性能是 B 樹的 1/6 ~ 1/3;
b.在限制寫入的狀況下;
LSM 樹的寫入性能與 B 樹的性能基本持平;
LSM 樹的讀取性能是 B 樹的 1/4 ~ 1/2;
場景:MongoDB默認存儲引擎使用了B樹,備用引擎是LSM樹。
Hbase中存儲設計使用了LSM樹。
問題1:Redis爲何採用跳錶而不是紅黑樹?
(1)插入、刪除、查找以及迭代輸出有序序列這幾個操做,紅黑樹也能夠完成,時間複雜度跟跳錶是同樣的。可是,按照區間來查找數據這個操做,紅黑樹的效率沒有跳錶高。
(2)跳錶插入和刪除更快、操做更簡單。平衡樹的插入和刪除操做可能引起子樹的旋轉調轉,邏輯複雜。
(3)算法實現簡單
(4)跳錶更加靈活,他能夠經過改變索引構建策略,有效平衡執行效率和內存消耗。
問題2:爲何MongoDB使用B樹,而mysql使用B+樹?
(1)B+樹內節點不存儲數據,全部 data 存儲在葉節點致使查詢時間複雜度固定爲 log n。
B-樹查詢時間複雜度不固定,與 key 在樹中的位置有關,最好爲O(1)
MongoDB追求單條記錄的效率發揮到極致,而不重視範圍查找(雖然也支持,可是性能不如B+樹)。
(2)B+樹擅長範圍查找,而B樹不擅長。(最重要的緣由)
B+樹查詢時間複雜度固定爲logn,性能穩定。
MySQL追求穩定和範圍查詢。
(3)B+樹中非葉子節點不存儲關鍵字,利於加載到內存。
問題3:B+樹、B樹對比?
(1)B+樹的全部數據都在葉子節點中,非葉子節點不存儲數據,只是索引。
B樹中的節點存儲數據;
(2)B+樹葉子節點之間是雙向鏈表。
B 樹中的葉子節點並不須要鏈表來串聯。
(3)B+樹更加適合範圍查詢、且查詢性能更穩定