索引
索引的出現其實就是為了提高資料查詢的效率,就像書的目錄一樣
n叉樹以innodb的乙個整數字段索引為例子,這個n差不多是1200。如果這棵樹高4的化,就可以儲存1200的3次方的值17億了。考慮到根節點總是在記憶體中的,那麼查乙個資料最多隻需要訪問3次磁碟,而且其中第二層也很有可能在記憶體中,那麼訪問磁碟的平均次數就更少了。
b+樹每乙個索引都有一顆b+樹
假如有這麼一張表,有乙個id為主鍵和乙個普通索引k的表
create table zx(
id int primary key,
k int not null,
name varchar(16),
index(k)
)engine=innodb;
如果有r1-r5(id,k)值分別為(100,1)、(200,2)、(300,3)、(500,5)和(600,6),那麼兩顆樹的樣子就如下圖
主鍵索引b+樹結構
主鍵索引的葉子節點存的是表的資料。在innodb裡,主鍵索引也叫聚簇索引(clustered index)
分主鍵索引b+樹結構
非主鍵索引的葉子節點內容是主鍵的值。在innodb裡,非主鍵索引也被稱為二級索引(secondary index)
區別
根據上面的內容,我們知道了資料是放在主鍵的索引結構中的,那麼我們查詢資料肯定最後會查詢主鍵的索引樹才會有資料。
案例
select * from zx where id=500
主鍵查詢,那麼只要搜尋主鍵的b+樹
select * from zx where k =5
非主鍵查詢,先搜尋k的索引b+樹,找到主鍵的值,在去查詢,主鍵的b+樹。這個過程被稱為回表
結論:盡量使用主鍵查詢,非主鍵查詢會多查詢一張表
索引的維護
b+樹是有序的
插入資料-自增主鍵
如果我們要插入乙個id為700的資料,那麼只需要在r5的記錄後面插入乙個新記錄就好了。
但是要插入乙個id為400那麼就麻煩了,需要拆分子節點,重新劃分上層結點,這樣的話就會很麻煩,耗時,消耗空間。同樣刪除操作也可能會觸發這個情況。
這就是為什麼推薦使用自增主鍵的原因了
主鍵長度越小,普通索引的葉子節點就越小,普通索引占用的空間越小
b+樹的優點
1.減少磁碟的io操作
2.加快資料查詢速度
覆蓋索引
引入
執行 select * from zx where k between 3 and 5會發生什麼?
表結構
create table zx(
id int primary key,
k int not null default 0,
s varchar(16) not null default '',
index k(k)
)engine=innodb;
表資料
執行流程
1.首先在k索引樹上找到k=3的記錄,取出id=300
2.再到id索引樹查到id=300對應的r3
3.在k索引樹上找到k=4的記錄,取出id=500
4.在回到id索引樹查到id=500的r4
5.在k索引樹查詢下乙個值為6,不滿足條件退出,返回結果
回到主鍵索引樹的搜尋過程叫做回表,這個過程查詢了k樹的3條記錄,回表了兩次
解決
使用覆蓋索引的方式:
select id from zx where k between 3 and 5
這樣查詢的id直接可以在k索引表查詢出來,所以就可以減少回表的操作,提高了資料查詢的效率
k索引表已經覆蓋了我們的查詢需求,所以叫覆蓋索引
聯合索引-索引結構
原理
聯合索引(col1, col2,col3)也是一棵b+tree,其非葉子節點儲存的是第乙個關鍵字的索引,而葉節點儲存的則是三個關鍵字col1、col2、col3三個關鍵字的資料,且按照col1、col2、col3的順序進行排序。
col1表示的是年齡,col2表示的是姓氏,col3表示的是名字
缺點
我們從圖中可以看出,起作用的索引其實就是聯合索引的第乙個索引,如果我們要查詢聯合索引的第二個索引,第三個索引其實是沒有效果的,相當於全表查詢。查詢第乙個和第三個索引的話,只有第乙個起效果,要繼續進行回表操作。所以聯合索引的第乙個索引設定是非常重要的。
聯合索引的覆蓋索引優化
我們從聯合索引的結構可以看出,索引樹是以第乙個索引構建的,但是在葉子節點儲存這索引2和索引3的資料,我們可以使用這種方式進行覆蓋索引的優化,減少回表操作。
案例
以上圖為例有乙個id主鍵,原來打算通過年齡範圍去查詢姓和名,那就要先通過年齡查出id,在通過id去查詢姓和名
但是直接以年齡和姓和名,這樣的話查詢年齡就可以直接得到姓和名的資料,省去了回表的操作
最左字首原則
問題
如果每一種查詢都要設計乙個索引,索引是不是太多了。單獨為乙個不頻繁的請求建立乙個索引也很浪費。
原則
1.這個最左字首可以是聯合索引的最左 n 個字段,也可以是字串索引的最左 m 個字元。
2.如果可以通過調整順序,可以少維護乙個索引,那麼這個順序往往就是需要優先考慮採用的。(比方說原來有(a,b)和b索引,我把順序調整成(b,a)那麼b索引就不需要了
有乙個復合索引:index(a, b, c)
使用方式 能否用上索引
select * from users where a = 1 and b = 2 能用上a、b
select * from users where b = 2 and a = 1 能用上a、b(有mysql查詢優化器)
select * from users where a = 2 and c = 1 能用上a
select * from users where b = 2 and c = 1 不能
說一下1和3的區別,1通過搜尋a和b直接可以獲得表的主鍵值,按照主鍵值查詢的資料全都是需要的資料
3的話,根據a查詢出來的主鍵值,並不是最終的結果,更具查詢出來的表資料在根據c欄位的要求篩選資料,效率會低一點
總結
在設計聯合索引的時候,聯合索引的個數和順序都需要精心的設計過,不可以隨便建立
索引下推
注意
索引下推是mysql5.6推出來的
查詢語句
select * from user where name like '張%' and age=10
如果是這樣查詢的話是不滿足最左字首原則的條件的,所以查詢效果如下
5.6mysql做了優化,在索引內部就判斷了age是否等於10,提高了效能
最左字首原則
b+樹
聯合索引
簡單的優化模型
以下是根據mooc西北工業大學肖老師數學建模課程整理的學習筆記 mooc指路 mooc數學建模 1.兩輛平板車裝貨問題 1 問題描述 有其中規格的包裝箱要裝到兩輛平板車上。包裝箱的寬和高是一樣的,但厚度t 厘公尺 和重量w 公斤 是不同的。表1給出了每種包裝箱的厚度,重量以及數量。表1 包裝箱引數資...
索引原理和優化
mysql的基本儲存結構是頁 記錄都存在頁裡邊 各個資料頁可以組成乙個雙向鍊錶 每個資料頁中的記錄又可以組成乙個單向鍊錶 使用索引後 沒有用索引我們是需要遍歷雙向鍊錶來定位對應的頁,現在通過 目錄 就可以很快地定位到對應的頁上了!二分查詢,時間複雜度近似為 o logn 其實底層結構就是 b 樹,b...
mysql索引模型 MySQL索引模型
資料庫索引的出現其實就是為了提高資料查詢的效率,就像書的目錄一樣。索引的常見模型 雜湊表陣列加鍊表實現,新增新資料較快,但是由於不是有序的,所以區間查詢速度是很慢的。雜湊表適用於只有等值查詢的場景,比如memcached及其他nosql引擎。有序陣列 有序陣列是講索引字段有序的存放在陣列中,所以在等...