MySQL索引機制詳解(B+樹)

1、索引是什麼?

  索引是爲了加速對錶中數據行的檢索而建立的一種分散存儲的數據結構。mysql

2、爲何要使用索引?

  1. 索引能極大的減小存儲引擎須要掃描的數據量。
  2. 索引能夠把隨機IO變成順序IO。
  3. 索引能夠幫助咱們在進行分組、排序等操做時,避免使用臨時表。

3、索引是什麼實現的?

  Indexes是第三方公司提供的可插拔的插件式存儲引擎。sql

  MySQL結構體系:數據庫

              

 4、爲何選用B+樹?

  一、Hash索引方式

            

   缺點:數據結構

  • 利用Hash存儲的話須要將全部的數據文件添加到內存,比較耗費內存空間。
  • 若是全部的查詢都是等職查詢,那麼hash確實很快,可是在企業或者實際工做環境中的範圍查找的數據更多,並且不是等值查詢,所以Hash就不適合了。

  二、二叉樹、紅黑樹索引方式

            

   缺點:性能

  • 太深:數據處的高/深度決定着他的IO操做次數, IO操做耗時大。應先把數據讀取效率。
  • 過小:每個磁盤塊(節點/頁)保存的數據量過小了。

  三、B樹(B-樹)的索引方式

  

  缺點:

  • B樹的每一個節點既有key又有data,可是每一個頁存儲的空間是有限的,若是data較大的話,那麼會致使每一個節點存儲的key數量變小。
  • 當存儲的數據量很大的時候會致使深度較大,增大查詢時候的磁盤IO次數,影響查詢性能。
  • Mysql查詢的時候使用到了大量的範圍查找,B樹在性能上並不能知足大量範圍查找。

  

  B+Tree與B-Tree的區別:

  • B+節點關鍵字搜索採用閉合區間。(MYSQL推崇使用ID做爲索引,因爲ID是自增的數字類型,只會增大,因此採用向右拓展的一個方式。)
  • B+非葉節點不保存數據相關信息, 只保存關鍵字和子節點的引用。
  • B+關鍵字對應的數據保存在葉子節點中。
  • B+葉子節點是順序排列的, 而且相鄰節點具備順序引用的關係。

  選擇B+Tree優勢:

  • B+樹是B-樹的變種( PLUS版) 多路絕對平衡查找樹, 他擁有B-樹的優點。
  • B+樹的葉子節點是順序排列的,且相鄰接點具備順序引用關係,所以在範圍查找時掃庫、 表能力更強,同時排序能力更強。
  • B+樹僅僅在葉子節點存儲數據,這樣索引文件更小,磁盤讀寫能力更強。
  • B+樹的樹高較低,索引文件較小,IO次數穩定,查詢效率更加穩定。

5、B+樹的索引實現方式

  查看數據存儲位置:優化

show variables like 'datadir';

  一、MyIsam

  索引和數據分別存儲。表定義存在.frm文件中(每一個存儲引擎都會有)。表中數據存在.MYD文件中。索引存在.MYI文件中。spa

            

  若是同一張表多個索引:插件

          

  每一個索引都存有每條數據的地址,一旦有變,維護起來比較耗時。 3d

  二、InnoDB

            

  數據就存在索引的葉子節點中。
  輔助索引:code

            

   其餘索引存主鍵,再從主鍵索引中找數據。

  注意:

  • InnoDB是經過B+樹結構對主鍵建立索引,而後葉子節點中儲存記錄,若是沒有主鍵,那麼會選擇惟一鍵,若是沒有惟一鍵,那麼會生成一個6位的row_id來做爲主鍵。
  • 若是建立索引的鍵是其餘字段,那麼在葉子節點中存儲的是該記錄的主鍵,而後再經過主鍵索引找到對應的記錄。  

6、索引注意事項

  一、聯合索引列選擇原則

  • 常常用的列優先 【 最左匹配原則】
  • 選擇性( 離散度) 高的列優先【 離散度高原則】(列的離散性越高,選擇性就越好。)
  • 寬度小的列優先【 最少空間原則】

  二、覆蓋索引

  若是查詢列可經過索引節點中的關鍵字直接返回, 則該索引稱之爲覆蓋索引。

  覆蓋索引可減小數據庫IO, 將隨機IO變爲順序IO, 可提升查詢性能。

  好比建立索引:

create index idx_name_phoneNum on users(name,phoneNum);

  查詢語句:

select name,phoneNum from user where name=?

  可直接從索引樹中返回關鍵字,不會再去查數據內容。

  三、其餘注意事項

  1. 索引列的數據長度能少則少。
  2. 索引必定不是越多越好, 越全越好, 必定是建合適的。
  3. 匹配列前綴可能用到索引 like 9999%, like %9999%、 like %9999用不到索引。like 9999%得看狀況,若是索引列離散性高,就能用到索引,離散性低,就用不到索引。
  4. Where 條件中 not in 和 <>操做沒法使用索引。
  5. 匹配範圍值, order by 也可用到索引。
  6. 多用指定列查詢, 只返回本身想到的數據列, 少用select * 以減小IO。
  7. 聯合索引中若是不是按照索引最左列開始查找, 沒法使用索引。在執行常量等值查詢時,改變索引列的順序並不會更改explain的執行結果,由於mysql底層優化器會進行優化,可是推薦按照索引順序列編寫sql語句。
  8. 聯合索引中精確匹配最左前列並範圍匹配另一列能夠用到索引。(索引列爲name,age的話,name=‘zhangsan’ and age>20)
  9. 聯合索引中若是查詢中有某個列的範圍查詢, 則其右邊的全部列都沒法使用索引。(索引列爲age,name的話,age>20 and name=‘zhangsan’)

附:B+樹添加和刪除數據圖解 (請放大查看)

相關文章
相關標籤/搜索