B+樹比B樹更適合做檔案資料庫索引
B樹:
B+樹:
B*樹是B+樹的變體,在B+樹的非根和非葉子結點再增加指向兄弟的指標;
B樹和B+樹在結構上的區別
1. B樹中關鍵字集合分佈在整棵樹中,葉節點中不包含任何關鍵字資訊,而B+樹關鍵字集合分佈在葉子結點中,非葉節點只是葉子結點中關鍵字的索引;
2. B樹中任何一個關鍵字只出現在一個結點中,而B+樹中的關鍵字必須出現在葉節點中,也可能在非葉結點中重複出現;
*B樹和B+樹在效能上的區別(也即為什麼說B+樹比B樹更適合實際應用中作業系統的檔案索引和資料庫索引?)
1. 不同於B樹只適合隨機檢索,B+樹同時支援隨機檢索和順序檢索;
2. B+樹的磁碟讀寫代價更低
3. B+樹的查詢效率更加穩定。B樹搜尋有可能會在非葉子結點結束,越靠近根節點的記錄查詢時間越短,只要找到關鍵字即可確定記錄的存在,其效能等價於在關鍵字全集內做一次二分查詢。而在B+樹中,順序檢索比較明顯,隨機檢索時,任何關鍵字的查詢都必須走一條從根節點到葉節點的路,所有關鍵字的查詢路徑長度相同,導致每一個關鍵字的查詢效率相當。
資料庫索引採用B+樹的主要原因是B樹沒有解決元素遍歷的效率低下的問題。B+樹的葉子節點使用指標順序連線在一起,只要遍歷葉子節點就可以實現整棵樹的遍歷。而且在資料庫中基於範圍的查詢是非常頻繁的,而B樹不支援這樣的操作(或者說效率太低),因此B+樹的元素遍歷效率比B樹高。
B+樹比B樹更加適合做檔案索引的原因:相對於B樹,
(1)B+樹空間利用率更高,可減少I/O次數,
一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。這樣的話,索引查詢過程中就要產生磁碟I/O消耗。而因為B+樹的內部節點只是作為索引使用,而不像B樹那樣每個節點都需要儲存硬碟指標。
也就是說:B+樹中每個非葉節點沒有指向某個關鍵字具體資訊的指標,所以每一個節點可以存放更多的關鍵字數量,即一次性讀入記憶體所需要查詢的關鍵字也就越多,減少了I/O操作。
e.g.假設磁碟中的一個盤塊容納16bytes,而一個關鍵字2bytes,一個關鍵字具體資訊指標2bytes。一棵9階B-tree(一個結點最多8個關鍵字)的內 部結點需要2個盤快。而B+ 樹內部結點只需要1個盤快。當需要把內部結點讀入記憶體中的時候,B 樹就比B+ 樹多一次盤塊查詢時間(在磁碟中就 是 碟片旋轉的時間)。
(2)增刪檔案(節點)時,效率更高,
因為B+樹的葉子節點包含所有關鍵字,並以有序的連結串列結構儲存,這樣可很好提高增刪效率。
(3)B+樹的查詢效率更加穩定,
因為B+樹的每次查詢過程中,都需要遍歷從根節點到葉子節點的某條路徑。所有關鍵字的查詢路徑長度相同,導致每一次查詢的效率相當。
B+樹在資料庫索引中的應用
目前大部分資料庫系統及檔案系統都採用B Tree或其變種B+Tree作為索引結構
1)在資料庫索引的應用
在資料庫索引的應用中,B+樹按照下列方式進行組織 :
① 葉結點的組織方式 。B+樹的查詢鍵 是資料檔案的主鍵 ,且索引是稠密的。也就是說 ,葉結點 中為資料檔案的第一個記錄設有一個鍵、指標對,該資料檔案可以按主鍵排序,也可以不按主鍵排序 ;資料檔案按主鍵排序,且 B +樹是稀疏索引 , 在葉結點中為資料檔案的每一個塊設有一個鍵、指標對 ;資料檔案不按鍵屬性排序 ,且該屬性是 B +樹 的查詢鍵 , 葉結點中為資料檔案裡出現的每個屬性K設有一個鍵 、 指標對 , 其中指標執行排序鍵值為 K的 記錄中的第一個。
② 非葉結點 的組織方式。B+樹 中的非葉結點形成 了葉結點上的一個多級稀疏索引。 每個非葉結點中至少有ceil( m/2 ) 個指標 , 至多有 m 個指標 。
2)B+樹索引的插入和刪除
①在向資料庫中插入新的資料時,同時也需要向資料庫索引中插入相應的索引鍵值 ,則需要向 B+樹 中插入新的鍵值。即上面我們提到的B-樹插入演算法。
②當從資料庫中刪除資料時,同時也需要從資料庫索引中刪除相應的索引鍵值 ,則需要從 B+樹 中刪 除該鍵值 。即B-樹刪除演算法
為什麼檔案系統及資料庫系統普遍採用B Tree或者B+Tree作為索引,而不用紅黑樹或者其他的資料結構?
二叉查詢樹進化品種的紅黑樹等資料結構也可以用來實現索引,但是檔案系統及資料庫系統普遍採用B/+Tree作為索引結構。
一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。這樣的話,索引查詢過程中就要產生磁碟I/O消耗,相對於記憶體存取,I/O存取的消耗要高几個數量級,所以評價一個數據結構作為索引的優劣最重要的指標就是在查詢過程中磁碟I/O操作次數的漸進複雜度。換句話說,索引的結構組織要儘量減少查詢過程中磁碟I/O的存取次數。為什麼使用B-/+Tree,還跟磁碟存取原理有關。
區域性性原理與磁碟預讀
由於儲存介質的特性,磁碟本身存取就比主存慢很多,再加上機械運動耗費,磁碟的存取速度往往是主存的幾百分分之一,因此為了提高效率,要儘量減少磁碟I/O。為了達到這個目的,磁碟往往不是嚴格按需讀取,而是每次都會預讀,即使只需要一個位元組,磁碟也會從這個位置開始,順序向後讀取一定長度的資料放入記憶體。這樣做的理論依據是電腦科學中著名的區域性性原理:
當一個數據被用到時,其附近的資料也通常會馬上被使用。
程式執行期間所需要的資料通常比較集中。
由於磁碟順序讀取的效率很高(不需要尋道時間,只需很少的旋轉時間),因此對於具有區域性性的程式來說,預讀可以提高I/O效率。
預讀的長度一般為頁(page)的整倍數。頁是計算機管理儲存器的邏輯塊,硬體及作業系統往往將主存和磁碟儲存區分割為連續的大小相等的塊,每個儲存塊稱為一頁(在許多作業系統中,頁得大小通常為4k),主存和磁碟以頁為單位交換資料。當程式要讀取的資料不在主存中時,會觸發一個缺頁異常,此時系統會向磁碟發出讀盤訊號,磁碟會找到資料的起始位置並向後連續讀取一頁或幾頁載入記憶體中,然後異常返回,程式繼續執行。
我們上面分析B-/+Tree檢索一次最多需要訪問節點:h=
資料庫系統巧妙利用了磁碟預讀原理,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現B- Tree還需要使用如下技巧:
每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也儲存在一個頁裡,加之計算機儲存分配都是按頁對齊的,就實現了一個node只需一次I/O。
B Tree中一次檢索最多需要h-1次I/O(根節點常駐記憶體),漸進複雜度為O(h)=O(logmN)。一般實際應用中,m是非常大的數字,通常超過100,因此h非常小(通常不超過3)。
綜上所述,用B Tree作為索引結構效率是非常高的。
而紅黑樹這種結構,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用區域性性,所以紅黑樹的I/O漸進複雜度也為O(h),效率明顯比B-Tree差很多。
為了儘量減少I/O操作,磁碟讀取每次都會預讀,大小通常為頁的整數倍。即使只需要讀取一個位元組,磁碟也會讀取一頁的資料(通常為4K)放入記憶體,記憶體與磁碟以頁為單位交換資料。因為區域性性原理認為,通常一個數據被用到,其附近的資料也會立馬被用到。
B-Tree:如果一次檢索需要訪問4個節點,資料庫系統設計者利用磁碟預讀原理,把節點的大小設計為一個頁,那讀取一個節點只需要一次I/O操作,完成這次檢索操作,最多需要3次I/O(根節點常駐記憶體)。資料記錄越小,每個節點存放的資料就越多,樹的高度也就越小,I/O操作就少了,檢索效率也就上去了。
B+Tree:非葉子節點只存key,大大滴減少了非葉子節點的大小,那麼每個節點就可以存放更多的記錄,樹更矮了,I/O操作更少了。所以B+Tree擁有更好的效能。
下面主要討論MyISAM和InnoDB兩個儲存引擎的索引實現方式:
1. MyISAM索引實現:
1)主鍵索引:
MyISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的是資料記錄的地址。下圖是MyISAM主鍵索引的原理圖:
這裡設表一共有三列,假設我們以Col1為主鍵,圖myisam1是一個MyISAM表的主索引(Primary key)示意。可以看出MyISAM的索引檔案僅僅儲存資料記錄的地址。
2)輔助索引(Secondary key)
在MyISAM中,主索引和輔助索引(Secondary key)在結構上沒有任何區別,只是主索引要求key是唯一的,而輔助索引的key可以重複。如果我們在Col2上建立一個輔助索引,則此索引的結構如下圖所示:
同樣也是一顆B+Tree,data域儲存資料記錄的地址。因此,MyISAM中索引檢索的演算法為首先按照B+Tree搜尋演算法搜尋索引,如果指定的Key存在,則取出其data域的值,然後以data域的值為地址,讀取相應資料記錄。
MyISAM的索引方式也叫做“非聚集”的,之所以這麼稱呼是為了與InnoDB的聚集索引區分。
2. InnoDB索引實現
然InnoDB也使用B+Tree作為索引結構,但具體實現方式卻與MyISAM截然不同.