B+樹,B樹,聚集索引,非聚集索引


簡介:

B+樹中只有葉子節點會帶有指向記錄的指針,而B樹則所有節點都帶有

B+樹索引可以分為聚集索引和非聚集索引

mysql使用B+樹,其中Myisam是非聚集索引,innoDB是聚集索引

聚簇索引索引的葉節點就是數據節點;而非聚簇索引的葉節點仍然是索引節點,只不過有一個指針指向對應的數據塊。

 

 

B樹:

 

 

B+樹:

 

 

 

B+ 樹的特點:

(1)所有關鍵字都出現在葉子結點的鏈表中(稠密索引),且鏈表中的關鍵字恰好是有序的;

(2)不可能在非葉子結點命中;

(3)非葉子結點相當於是葉子結點的索引(稀疏索引),葉子結點相當於是存儲(關鍵字)數據的數據層;

 
image.png

如圖所示,區別有以下兩點:

結構上

  1. B+樹中只有葉子節點會帶有指向記錄的指針,而B樹則所有節點都帶有,在內部節點出現的索引項不會再出現在葉子節點中。
  2. B+樹中所有葉子節點都是通過指針連接在一起,而B樹不會。

性能上(也即為什么說B+樹比B樹更適合實際應用中操作系統的文件索引和數據庫索引?)

  • 不同於B樹只適合隨機檢索,B+樹同時支持隨機檢索和順序檢索
  • B+樹的磁盤讀寫代價更低。B+樹的內部結點並沒有指向關鍵字具體信息的指針,其內部結點比B樹小,盤塊能容納的結點中關鍵字數量更多,一次性讀入內存中可以查找的關鍵字也就越多,相對的,IO讀寫次數也就降低了。而IO讀寫次數是影響索引檢索效率的最大因素。
  • B+樹的查詢效率更加穩定。B樹搜索有可能會在非葉子結點結束,越靠近根節點的記錄查找時間越短,只要找到關鍵字即可確定記錄的存在,其性能等價於在關鍵字全集內做一次二分查找。而在B+樹中,順序檢索比較明顯,隨機檢索時,任何關鍵字的查找都必須走一條從根節點到葉節點的路,所有關鍵字的查找路徑長度相同,導致每一個關鍵字的查詢效率相當。
  • (數據庫索引采用B+樹的主要原因是,)B-樹在提高了磁盤IO性能的同時並沒有解決元素遍歷的效率低下的問題。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-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差很多。

 

 

聚集索引,非聚集索引

根本區別
    聚集索引和非聚集索引的根本區別是表記錄的排列順序和與索引的排列順序是否一致。

聚集索引

    聚集索引表記錄的排列順序和索引的排列順序一致,所以查詢效率快,只要找到第一個索引值記錄,其余就連續性的記錄在物理也一樣連續存放。聚集索引對應的缺點就是修改慢,因為為了保證表中記錄的物理和索引順序一致,在記錄插入的時候,會對數據頁重新排序。

非聚集索引
    非聚集索引制定了表中記錄的邏輯順序,但是記錄的物理和索引不一定一致,兩種索引都采用B+樹結構,非聚集索引的葉子層並不和實際數據頁相重疊,而采用葉子層包含一個指向表中的記錄在數據頁中的指針方式。非聚集索引層次多,不會造成數據重排。
例子對比兩種索引
    聚集索引就類似新華字典中的拼音排序索引,都是按順序進行,例如找到字典中的“愛”,就里面順序執行找到“癌”。而非聚集索引則類似於筆畫排序,索引順序和物理順序並不是按順序存放的。

 

mysql使用B+樹,其中Myisam是非聚集索引,innoDB是聚集索引

1. MyISAM索引實現:

1)主鍵索引:

MyISAM引擎使用B+Tree作為索引結構,葉節點的data域存放的是數據記錄的地址。下圖是MyISAM主鍵索引的原理圖:


                                                                           (圖myisam1)

這里設表一共有三列,假設我們以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截然不同.

1)主鍵索引:

         MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。而在InnoDB中,表數據文件本身就是按B+Tree組織的一個索引結構,這棵樹的葉節點data域保存了完整的數據記錄。這個索引的key是數據表的主鍵,因此InnoDB表數據文件本身就是主索引。

               (圖inndb主鍵索引)

 (圖inndb主鍵索引)是InnoDB主索引(同時也是數據文件)的示意圖,可以看到葉節點包含了完整的數據記錄。這種索引叫做聚集索引。因為InnoDB的數據文件本身要按主鍵聚集,所以InnoDB要求表必須有主鍵(MyISAM可以沒有),如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵,這個字段長度為6個字節,類型為長整形。

2). InnoDB的輔助索引

       InnoDB的所有輔助索引都引用主鍵作為data域。例如,下圖為定義在Col3上的一個輔助索引:

 

 

 

        InnoDB 表是基於聚簇索引建立的。因此InnoDB 的索引能提供一種非常快速的主鍵查找性能。不過,它的輔助索引(Secondary Index, 也就是非主鍵索引)也會包含主鍵列,所以,如果主鍵定義的比較大,其他索引也將很大。如果想在表上定義 、很多索引,則爭取盡量把主鍵定義得小一些。InnoDB 不會壓縮索引。

      文字符的ASCII碼作為比較准則。聚集索引這種實現方式使得按主鍵的搜索十分高效,但是輔助索引搜索需要檢索兩遍索引:首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。

      不同存儲引擎的索引實現方式對於正確使用和優化索引都非常有幫助,例如知道了InnoDB的索引實現后,就很容易明白為什么不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。再例如,用非單調的字段作為主鍵在InnoDB中不是個好主意,因為InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。

 

 InnoDB索引MyISAM索引的區別:

一是主索引的區別,InnoDB的數據文件本身就是索引文件。而MyISAM的索引和數據是分開的。

二是輔助索引的區別:InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。而MyISAM的輔助索引和主索引沒有多大區別。

 

https://blog.csdn.net/mine_song/article/details/63251546?utm_source=copy

https://blog.csdn.net/jiadajing267/article/details/54581262?utm_source=copy


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM