MySQL索引演算法之B Tree

2021-08-29 10:22:16 字數 2868 閱讀 3127

b-tree索引

當人們談論索引的時候,如果沒有特別指明型別,  那多半說的是b-tree索引,它使用b- tree資料結構來儲存資料。大多數mysql引擎都支援這種索引。archive 引擎是乙個例外: 5.1之前archive不支援任何索引,直到5.1才開始支援單個自增列(auto_increment)的索引。

我們使用術語「b-tree",是因為mysql在create table 和其他語句中也使用該關鍵字。

不過,  底層的儲存引擎也可能使用不同的儲存結構,例如,ndb集群儲存引擎內部實際.上使用了t-tree結構儲存這種索引,  即使其名字是btree ; innodb則使用的是b+tree。

儲存引擎以不同的方式使用b-tree索引,效能也各有不同,各有優劣。例如,myisam使用字首壓縮技術使得索引更小,但innodb則按照原資料格式進行儲存。  再如myisam索引通過資料的物理位置引用被索引的行,而innodb則根據主鍵引用被索引的行。

b-tree通常意味著所有的值都是按順序儲存的,並且每-乙個葉子頁到根的距離相同。圖5-1展示了b-tree索引的抽象表示,大致反映了innodb索引是如何工作的。myisam使用的結構有所不同,但基本思想是類似的。

b-tree索引能夠加快訪問資料的速度,因為儲存引擎不再需要進行全表掃瞄來獲取需要的資料,  取而代之的是從索引的根節點(圖示並未畫出)開始進行搜尋。根節點的槽中存放了指向子節點的指標,儲存引擎根據這些指標向下層查詢。通過比較節點頁的值和要查詢的值可以找到合適的指標進入下層子節點,這些指標實際上定義了子節點頁中值的上限和下限。最終儲存引擎要麼是找到對應的值,要麼該記錄不存在。

葉子節點比較特別,它們的指標指向的是被索引的資料,而不是其他的節點頁  (不同引擎的「指標」型別不同)。圖5-1中僅繪製了乙個節點和其對應的葉子節點,其實在根節點和葉子節點之間可能有很多層節點頁。樹的深度和表的大小直接相關。

b-tree對索引列是順序組織儲存的,所以很適合查詢範圍資料。例如,在一乙個基於文字域的索引樹上,  按字母順序傳遞連續的值進行查詢是非常合適的,  所以像「找出所有以i到k開頭的名字」這樣的查詢效率會非常高。

假設有如下資料表:

create table people (

last_ name varchar(50)

first_ name varchar (50)  not null,dob  dategender

key(last_ name, first_ name, dob)

);對於表中的每一行資料,索引中包含了last_ name、 first_ name 和dob列的值,示了該索引是如何組織資料的儲存的。

請注意,索引對多個值進行排序的依據是create table語句中定義索引時列的順序。看一下最後兩個條目,兩個人的姓和名都一樣,則根據他們的出生日期來排列順序。

可以使用b-tree索引的查詢型別。b-tree 索引適用於全鍵值、鍵值範圍或鍵字首查詢。其中鍵字首查詢只適用於根據最左字首的查詢生了。前面所述的索引對如下型別的查詢有效。

全值匹配

全值匹配指的是和索引中的所有列進行匹配,例如前面提到的索引可用於查詢姓名為cuba allen、出生於1960-01-01的人。匹配最左字首

前面提到的索引可用於查詢所有姓為allen的人,即只使用索引的第一列。匹配列字首

也可以只匹配某一列的值的開頭部分。例如前面提到的索引可用於查詢所有以j開頭的姓的人。這裡也只使用了索引的第-一列。匹配範圍值

例如前面提到的索引可用於查詢姓在allen和barrymore之間的人。這裡也只使用了索引的第-列。

精確匹配某一-列並範圍匹配另外一列

前面提到的索引也可用於查詢所有姓為allen,並且名字是字母k開頭(比如kim、karl等)的人。即第- -列last_ name 全匹配,第二列first_ name 範圍匹配。只訪問索引的查詢

b-tree通常可以支援「只訪問索引的查詢」,即查詢只需要訪問索引,而無須訪問資料行。後面我們將單獨討論這種「 覆蓋索引」的優化。

因為索引樹中的節點是有序的,所以除了按值查詢之外,索引還可以用於查詢中的order by 操作(按順序查詢)。-般來說,如果b-tree可以按照某種方式查詢到值,那麼也可以按照這種方式用於排序。所以,如果order by子句滿足前面列出的幾種查詢類

型,則這個索引也可以滿足對應的排序需求。

下面是一些關於b-tree索引的限制:

如果不是按照索引的最左列開始查詢,  則無法使用索引。例如_上面例子中的索引無法用於查詢名字為bill的人,  也無法查詢某個特定生日的人,  因為這兩列都不是最左資料列。類似地,也無法查詢姓氏以某個字母結尾的人。

不能跳過索引中的列。也就是說,前面所述的索引無法用於查詢姓為smith並且在某個特定日期出生的人。如果不指定名(first_ name), 則mysql只能使用索引的第一列。

如果查詢中有某個列的範圍查詢,則其右邊所有列都無法使用索引優化查詢。例如有查詢where  last_ name=' smith' and  first name  like  'j%'  and dob = '1976-12-23',這個查詢只能使用索引的前兩列,因為這裡like是一乙個範圍條件(但是伺服器可以把其餘列用於其他目的)。如果範圍查詢列值的數量有限,那麼可以通過使用多個等於條件來代替範圍條件。在本章的索引案例學習部分,我們將演示一乙個詳細的案例。

到這裡讀者應該可以明白,前面提到的索引列的順序是多麼的重要:這些限制都和索引列的順序有關。在優化效能的時候,可能需要使用相同的列但順序不同的索引來滿足不同型別的查詢需求。

也有些限制並不是b-tree本身導致的,而是mysql優化器和儲存引擎使用索引的方式導致的,這部分限制在未來的版本中可能就不再是限制了。

mysql之BTree索引 和 雜湊索引

排好序的快速查詢資料結構。索引會影響where後面的查詢,和order by 後面的排序。基於雜湊表實現,只有精確匹配索引所有列的查詢才有效。對於每一行資料,儲存引擎都會對所有的索引列計算乙個雜湊碼 hash code 並且hash索引將所有的雜湊碼儲存在索引中,同時在索引表中儲存指向每個資料行的指...

MySQL的索引,B tree還是B tree

如果你用 show index from table 得到的index type為 btree 但是我們印象中不是應該是b 樹麼?這個鏈結裡給出了大概的解答 does mysql use b tree,b tree or both?b tree would be a very bad keyword...

oracle 索引 之B TREE 索引

索引是oracle裡面的乙個非常重要的知識,oracle10g中索引可以分為以下 b tree indexes b tree cluster indexes hash cluster indexes reverse key indexes bitmap indexes bitmap join ind...