簡談mysql索引之聯合索引

2021-10-25 05:31:34 字數 3413 閱讀 7078

我們程式設計師日常工作中打交道最多的就是聯合索引,基本上索引優化就是優化這一塊。講聯合索引,一定要扯上最左匹配原則。不廢話,直接進入正文。(注:本文是在innodb的基礎上討論和實驗的。)

所謂最左原則指的就是如果你的 sql 語句中用到了聯合索引中的最左邊的索引,那麼這條 sql 語句就可以利用這個聯合索引去進行匹配,值得注意的是,當遇到範圍查詢(>、

假設,我們對(col1,col2)字段建立乙個索引,也就是說,你where後條件為

col1= 1

col1= 1 and col2= 2

是可以匹配索引的。但是要注意的是~你執行

col2= 2 and col1=1
也是能匹配到索引的,因為mysql有優化器會自動調整a,b的順序與索引順序一致。

但是你執行

col2= 2
就匹配不到索引了。

而你對(col1,col2,col3,col4)建立索引,where後條件為

col1= 1 and col2= 2 and col3> 3 and col4= 4
那麼,col1,col2,col3三個欄位能用到索引,而col4就匹配不到。因為遇到了範圍查詢!

理解最左匹配原則之前最好了解一下b+樹,因為innodb儲存引擎預設是用b+樹作為索引的結構。

假設,我們對(col1,col2)字段建立索引,那麼如下圖所示:

如圖所示他們是按照col1來進行排序,在col1相等的情況下,才按col2來排序。

因此,我們可以看到col1是有序的1,1,2,2,3,3。而col2是一種全域性無序,區域性相對有序狀態!

什麼意思呢?

從全域性來看,col2的值為1,2,1,4,1,2,是無序的,因此直接執行col2 = 2這種查詢條件沒有辦法利用索引。

從區域性來看,當col1的值確定的時候,col2是有序的。例如col1 = 1時,col2值為1,2是有序的狀態。當col1 = 2時候,col2的值為1,4也是有序狀態。

因此,你執行col1 = 1 and col2 = 2時col1,col2欄位能用到索引的。而你執行col1 > 1 and col2 = 2時,col1欄位能用到索引,col2欄位用不到索引。因為col1 的值此時是乙個範圍,不是固定的,在這個範圍內col2值不是有序的,因此col2欄位用不上索引。

綜上所示,最左匹配原則,在遇到範圍查詢的時候,就會停止匹配。

有了上面的基礎,再看下面的五大題型,看完基本就懂!

題型一

如果sql為

select * from t_tbl where  col1 =1 and col2 = 2 and col3 = 3;
如何建立索引?

如果此題回答為對(col1 ,col2,col3)建立索引,那都可以回去等通知了。

此題正確答法是:(col1 ,col2,col3)或者(col2 ,col1,col3)或者(col3 ,col2,col1)都可以,重點要的是將區分度高的字段放在前面,區分度低的字段放後面。像性別、狀態這種字段區分度就很低,我們一般放後面。

例如假設區分度由大到小為col2,col1,col3。那麼我們就對(col2,col1,col3)建立索引。在執行sql的時候,優化器會幫我們調整where後col1,col2,col3的順序,讓我們用上索引。

題型二

如果sql為

select * from table 

where col1> 1 and col2 = 2;

如何建立索引?

如果此題回答為對(col1,col2)建立索引,那都可以回去等通知了。

此題正確答法是,對(col2 ,col1)建立索引。如果你建立的是(col1,col2)索引,那麼只有col1欄位能用得上索引,畢竟最左匹配原則遇到範圍查詢就停止匹配(注:如果表的資料很大,可能col1欄位也用不上索引,因為mysql認為資料檢索量已經超過某個閾值,就會自動進行全表掃瞄,所以索引失效。)。

如果對(col2,col1)建立索引那麼兩個欄位都能用上,優化器會幫我們調整where後col1,col2的順序,讓我們用上索引。

題型三

如果sql為

select * from `table` 

where col1> 1 and col2= 2 and col3> 3;

如何建立索引?

此題回答也是不一定,(col2,col1)或者(col2,col3)都可以,要結合具體情況具體分析。

拓展一下

select * from table

where col1= 1 and col2= 2 and col3> 3;

怎麼建索引?嗯,大家一定都懂了!

題型四

如果sql為

select * from table where col1 = 1 order by col2;
如何建立索引? 這還需要想?一看就是對(col1,col2)建索引,當col1 = 1的時候,col2相對有序,可以避免再次排序! 那麼

select * from `table` 

where col1 > 1 order by col2;

如何建立索引?

對(col1)建立索引,因為a的值是乙個範圍,這個範圍內col2值是無序的,沒有必要對(col1,col2)建立索引。

拓展一下

select * from `table` 

where col1= 1 and col2= 2 and col3>3 order by c;

怎麼建索引?

題型五

select * from `table` where col1 in (1,2,3) and col2 > 1;
如何建立索引?

還是對(col1,col2)建立索引,因為in在這裡可以視為等值引用,不會中止索引匹配,所以還是(col1,col2)!

拓展一下

select * from `table` where col1 = 1 and col2 in (1,2,3) and col3 > 3 order by col3 ;
如何建立索引?此時col3 排序是用不到索引的。

mysql索引簡談

mysql索引簡談 一 什麼是索引 就好比我們在看一本書的時候,有目錄的話,我們可以快速定位到想看的地方,而沒有目錄的話,我們只能一頁一頁地翻。索引就像目錄,有了索引,資料庫可以快速查詢到目標內容,而不必查詢整個資料庫表,但是如果沒有的話,資料庫只能一行一行地遍歷資料。create table t ...

MYSQL索引之聯合索引詳解

比較簡單的是單列索引 b tree 遇到多條件查詢時,不可避免會使用到多列索引。聯合索引又叫復合索引。b tree結構如下 每乙個磁碟塊在mysql中是乙個頁,頁大小是固定的,mysql innodb的預設的頁大小是16k,每個索引會分配在頁上的數量是由字段的大小決定。當字段值的長度越長,每一頁上的...

索引欄 mysql之聯合索引

前期準備 建立聯合索引?create table test id bigint 16 not null auto increment,aaa varchar 16 not null,bbb varchar 16 not null,ccc int 11 not null,primary key id ...