索引模型 和簡單優化

2022-01-20 12:54:43 字數 4300 閱讀 4513

索引

索引的出現其實就是為了提高資料查詢的效率,就像書的目錄一樣

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引擎。有序陣列 有序陣列是講索引字段有序的存放在陣列中,所以在等...