mysql的索引本质是一颗_一文揭开Mysql索引本质
文章目錄
什么是索引
索引的分類
索引的本質
HASH
B+樹
Mysql存儲引擎
InnoDB
MyISAM
試驗
結語
什么是索引
眾所周知,索引是用來加快數據庫查詢速度的,試想一條sql語句:select * from my_table where id = 10000,如果沒有索引,那么就必須要遍歷整張表,直到找到id=10000這一行數據,這樣做無疑是低效的。而如果在id這一列上建立了索引,就可在索引中查找。由于索引是經過某種算法優化過的,因而查找次數要少的多。可以極大的提高查詢速度。
索引的分類
普通索引:僅用來加速查詢。
唯一索引:加速查詢+列值唯一(允許為null)。
主鍵索引:加速查詢+列值唯一(不允許為null),一張表只能由一個主鍵索引。
聯合索引:多個列值組成一個索引,用于組合搜索,其效率大于索引合并。
全文索引:對文本的內容進行分詞,解決判斷字段是否包含的問題。(實際中使用較少)
索引的本質
mysql默認的索引方式是B+樹,用戶也可以選擇HASH,下面依次介紹這兩種方式
HASH
哈希函數會根據傳入的關鍵字計算出其所在的位置,它會將關鍵字域映射到哈希表中的一個位置上。,我們在查詢的時候,只需要進行一次運算后就可以找到該行數據對應的下標位置,時間復雜度為O(1),但是它有幾個很明顯的缺點:
浪費數據空間,HASH表中很多地方是沒有存數據的。
不支持范圍查詢。
不支持排序。
基于以上幾個缺點,雖然HASH進行查詢時速度很快,但是Mysql不將它作為
默認索引方式。
B+樹
m階B+樹的性質:
每個節點最多有m個子節點。
除根節點外,每個節點至少有m/2個子節點,注意如果結果除不盡,就向上取整,比如5/2=3。
根節點要么是空,要么是獨根,否則至少有2個子節點。
有k個子節點的節點必有k個關鍵碼。
葉節點的高度一致。
數據只存在于葉節點中。
下圖給出了一個3階的B+樹的結構
葉子節點順序排列,數據全部存放在葉子節點中(也稱為衛星數據),其余節點僅存放索引,同時葉子節點通過組成一個雙向鏈表。
從圖中可以看出,每一個子節點中的最大值都能在其父節點中找到,看著是不是有點像二叉搜索樹呢?與之不同的是,B+樹每一個節點都能存放多個數據。
這里舉一個例子,假設我們想找大于5,小于16的數據,B+樹從根節點像下找的過程如下:
B+樹的查詢效率很高,而且很適合范圍查詢。
有點朋友可能會問了,我們應該如何選擇B+樹的階數呢?
大家都知道,數據庫查詢的瓶頸在于磁盤IO,而數據是存在我們的磁盤上的,我們應該盡可能減少磁盤IO次數,那么應盡量把數據存在一個磁盤塊中,由于磁盤塊的大小一般是4KB,所以M階B+樹的M值應盡可能向它靠攏,我們一般取4KB的0.75倍。同時,由于除葉子節點外其余節點沒有存衛星數據,所以這些節點能存放更多的索引。這也減小了磁盤的IO。
Mysql存儲引擎
InnoDB
InnoDB是mysql默認的存儲引擎,它采用聚集索引,支持事務。
這兒提到了聚集索引,那么什么是聚集索引呢?
聚集索引就是將數據文件和索引放在一起,也就是說當我們通過索引進行查詢的時候,能夠直接找到數據。
這里以主鍵ID對應的索引為例
可以看到索引和數據文件是放在一起的。(這里的data指的是對應行包含所有列值的整行數據,不單單只是一個數據)
而當使用輔助索引(非主鍵字段建立的索引)進行查詢時,索引值是和該行對應的主鍵值放在一起的,這就意味這查詢時先找到該行主鍵ID,然后再通過這個主鍵ID值在主鍵的索引樹下找到數據。
MyISAM
mysql也提供MyISAM存儲引擎,MyISAM采用非聚集索引,查詢效率高,但不支持事務。
什么是非聚集索引呢?
非聚集索引就是索引和數據是分開放的。
那么怎么通過索引找到數據呢?
請看下面的索引樹
雖然數據和索引是分開的,但每一個索引下面存的是該行數據對應的地址,也就是說我們可以拿到該行數據的地址,那么直接尋址就可以找到數據。
試驗
下面我們來通過一個試驗直觀的感受兩個存儲引擎的不同。
首先先創建一個數據庫
create database test_db;
然后看到我的mysql安裝目錄的data文件夾下多了一個test_db文件夾,進入文件夾,現在文件夾是空的。
選擇剛剛創建的數據庫。
use test_db;
然后創建一張使用InnoDB存儲引擎的表,由于mysql默認使用InnoDB,所以可以不指定引擎。
create table user1(id int primary key auto_increment,name varchar(20));
然后再看test_db文件夾。
可以看到多了一個user1.ibd文件,這個表的索引和數據是放在一個文件中的。
我們再創建一張使用MyISAM存儲引擎的表,這里需要顯示指定引擎。
create table user2(id int primary key auto_increment,name varchar(20))engine=myisam charset=utf8;
然后再看test_db文件夾。
可以看到多了user2.MYD和user2.MYI
其中user2.MYD存放的的是表的數據文件,而user2.MYI存放的是表的索引文件。
結語
索引能大大的提高我們的工作效率,但索引是有開銷的,當我們的數據量很小時也沒有建索引的必要,希望這篇文章能讓大家認識到索引的本質。
總結
以上是生活随笔為你收集整理的mysql的索引本质是一颗_一文揭开Mysql索引本质的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: eclipse java shell 窗
- 下一篇: mysql第一二章笔记_MYSQL必知必