這些問題是在實現索引時遇到的,我利用b+樹實現了索引,整個索引包括以下三個部分:b+樹結點,關鍵字和鏈結結點。b+樹結點儲存在索引頁中。鏈結結點是為了解決重複關鍵字的問題而設計的,所有重複關鍵字的資料行在資料頁的位址在b+樹的葉結點以單鏈表的形式鏈結起來,其實就是拉鍊法解決衝突,整個鍊錶儲存在鏈結頁中。
b+樹的key域是乙個64位的資料型別,只能儲存整型或者實型的關鍵字,因此要實現對字串型別的字段或者多字段的復合索引,只能將被索引的字段值提出來作為關鍵字單獨儲存在關鍵字頁中,然後用key域儲存該關鍵字在關鍵字頁中的位址,下面是一張圖,描述了各個結構之間的聯絡。
該索引的查詢過程是,從根節點開始,用二分查詢找到當前結點第乙個大於等於key的關鍵字,然後再繼續查詢該關鍵字的孩子結點,直到搜尋到葉結點。
實現上述索引結構後,我用350w行的表進行了索引查詢效率測試,發現在某些情況下,定位一資料行的缺頁次數竟然達到了20多次,而相同情況下mysql索引定位一資料行的缺頁次數不超過7次。經過分析,在最壞的情況下,在包含n個關鍵字,階為2d+1的上述結構的索引中查詢乙個關鍵字的缺頁次數是log(2)(d)*log(d)(n)+ log(d)(n)= log(2)(n)+log(d)(n)次,當n=350w,d=10時缺頁次數是37次。這樣的i/o次數是不可以容忍的,效率很低。
查詢上述索引結構時,多數的時間花在讀取b+樹結點的關鍵字上,為了避免這種情況,可以將關鍵字直接儲存在b+樹結點的key域中,這樣最壞情況下的缺頁次數為log(d)(n),缺頁次數僅為7次左右,但由於b+樹結點不能跨頁儲存,因此必須對關鍵字的長度進行限制。myisam中關鍵字的長度必須小於767,而mysql頁的容量是16k,假如每頁只儲存乙個b+樹結點,那麼myisam中b+樹的階最大也就是21左右。
我把b+樹結點改為上圖結構,再對350w行資料建立索引,發現整個索引的尺寸竟然超過了5g,原因是key域是定長的,絕大部分的關鍵字也就是十幾位元組,大多數的空間都被浪費了。為解決這種空間利用率太低的問題,我可以把key設定為變長的,但如果key域是變長的,那麼在b+樹結點a和b合併時,肯定會發生因為空間限制不能將b合併到a中,必須新申請個c,然後將a,b拷貝到c中的情況,這樣會使索引頁中的碎片很多,降低索引的效率,因此非常糾結。
到這裡,我有乙個疑問,innodb的輔助b+樹索引中頁結點和非頁結點的key域儲存的是什麼?,是如何組織的?
實現簡單爬蟲中遇到的問題
python2.7 中使用的是urllib2 python3.6 中使用的是urllib python2.7 中使用的是urlparse python3.6 中使用的是urllib.parse 解決方式 給模組檔案新增 usr bin env python3 作用 run a program in ...
MyBatis 實現樂觀鎖遇到的問題
mybatis 通過版本號方式實現樂觀鎖 1.先查詢出 select status,version from t table where status 1 and xx 2.修改使用狀態status為2 update t table set status 2,version version 1 wh...
遇到的問題
1 若class cnmdevctrlprotocol virtual public cnetcomm則starttimer編譯通不過 2 activex在ie下載入多個,相當於多執行緒,所以這時候的activex不要使用全域性變數,當時如果編寫動態庫也不要使用全域性變數 3 btn灰顯或sleep...