mysql 5 回表 覆蓋索引 最左匹配原則

2021-10-04 04:35:02 字數 3632 閱讀 9838

回表

通過上一章的介紹,我們知道索引可以分為主鍵索引和非主鍵索引。非主鍵索引的葉子節點儲存的是主鍵索引的值。

我們在通過非主鍵索引查詢時候,需要先在非主鍵索引樹找到主鍵值,然後再到主鍵索引樹根據主鍵值去查詢出整行資料,這個過程中,回到主鍵索引樹搜尋的過程,我們稱為回表

覆蓋索引

#建立一張表

mysql>

create

table t (

id int

primary

key,

k int

notnull

default0,

s varchar(16

)not

null

default'',

index k(k)

)engine

=innodb

;#插入的資料

insert

into t values

(100,1

,'aa'),

(200,2

,'bb'),

(300,3

,'cc'),

(500,5

,'ee'),

(600,6

,'ff'),

(700,7

,'gg'

);

索引樹的結構為:

對於上面的表我們執行下面這條查詢語句:select id from t where k between 3 and 5

這個時候,輸出列只需要查詢id,而索引樹k上面已經有id資訊了,因此可以直接返回結果,不用再去id主鍵索引樹上搜尋了,就避免了回表

也就是說,在這個查詢裡面,索引 k 已經「覆蓋了」我們的查詢需求,我們稱為覆蓋索引

tips:由於覆蓋索引可以減少樹的搜尋次數,顯著提公升查詢效能,所以使用覆蓋索引是乙個常用的效能優化手段。

例如:我們公司的內部通訊軟體,經常會用員工工號查詢員工姓名,這樣乙個高頻搜尋需求,那麼我們就可以建立乙個(工號,姓名)的聯合索引,通過合理使用聯合索引,來實現覆蓋索引,提高查詢效率。

當然,索引欄位的維護總是有代價的。因此,在建立冗餘索引來支援覆蓋索引時就需要權衡考慮了。

最左匹配原則

我們建立乙個聯合索引 idx_abc(a,b,c)

查詢條件

索引是否生效

where a=# and b=# and c=#

idx_abc生效

where c=# and b=# and a=#

idx_abc生效(特殊性情況,優化器會處理,最後又會變成abc順序)

where a=# and b=#

idx_abc生效

where a=#

idx_abc生效

where a=# and c=#

idx_abc生效

where b=#

idx_abc不生效

where c=#

idx_abc不生效

where b=# and c=#

idx_abc不生效

可以看到,不只是索引的全部定義,只要滿足最左字首,就可以利用索引來加速檢索。這個最左字首可以是聯合索引的最左 n 個字段,也可以是字串索引的最左 m 個字元。

查詢條件的第乙個一定要和聯合索引順序匹配上,否則索引失效。這個時候,如果我們欄位c才是高頻搜尋條件呢,我們又不能不建索引,所以只能新建乙個idx_c(c)的索引。但是我們是否可以考慮,調整索引順序,將idx_abc(a,b,c)改為idx_abc(c,b,a)呢?這樣我們就不用單獨去建立乙個idx_c索引了。當然這個是否可以這麼修改還是要看實際業務場景。

如果對於聯合索引idx_ab(a,b),既有聯合的查詢,又有基於a ,b各自的查詢。那我們是建立(a,b)(b)這兩個索引還是建立(b,a)(a)這兩個索引呢?那麼需要考慮單獨的這個索引怎麼樣可以占用更少的磁碟空間

給大家貼個表結構,大家可以親自動手試下

create

table

`t_test`

(`id`

int(11)

default

null

,`a`

varchar

(255

)default

null

,`b`

varchar

(255

)default

null

,`c`

varchar

(255

)default

null

,key

`idx_abc`

(`a`

,`b`

,`c`))

engine

=innodb

default

charset

=utf8;

insert

into

`t_test`

(`id`

,`a`

,`b`

,`c`

)values

('1'

,'a1'

,'b1'

,'c1');

insert

into

`t_test`

(`id`

,`a`

,`b`

,`c`

)values

('2'

,'a2'

,'b2'

,'c3');

#通過explain來看下索引是否生效

explain

select

*from t_test where a=

'a1'

and b=

'b1'

and c=

'c1'

explain

select

*from t_test where a=

'a1'

and b=

'b1'

explain

select

*from t_test where a=

'a1'

explain

select

*from t_test where b=

'b1'

explain

select

*from t_test where c=

'c1'

explain

select

*from t_test where a=

'a1'

and c=

'c1'

explain

select

*from t_test where b=

'b1'

and c=

'c1'

explain

select

*from t_test where c=

'c1'

and b=

'b1'

and a=

'a1'

MySQL innodb索引回表操作,最左匹配

簇集索引 主鍵索引 索引的葉子結點存的所有字段值,非簇集索引 非主鍵索引 索引的葉子結點存的是主鍵欄位的值 回表操作 例子 表table 有主鍵 a,索引b select a,b,c from table where a 1 因為a是簇集索引有所有字段,不會回表查 select a,b,c from...

Mysql索引 回表 索引覆蓋

1.先說什麼是索引?索引是一種資料結構 不同引擎對索引的實現方式不同,innodb採用b 樹作為索引結構。2.聚簇索引 非聚簇索引索引可分為聚簇索引和非聚簇索引兩種。聚簇索引 clustered index 聚簇索引的資料的物理存放順序與索引順序是一致的。非聚簇索引 二級索引 secondary i...

MySQL索引,回表,索引覆蓋

多讀多寫多記錄,多學多練多思考。banana.banuit gang 香柚幫 mysql innodb的主鍵索引是簇集索引,也就是索引的葉子節點存的是整個單條記錄的所有字段值,不是主鍵索引的就是非簇集索引,非簇集索引的葉子節點存的是主鍵欄位的值。回表是什麼意思?就是你執行一條sql語句,需要從兩個b...