日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

MYSQL | 最左匹配原则

發(fā)布時間:2023/12/13 综合教程 26 生活家
生活随笔 收集整理的這篇文章主要介紹了 MYSQL | 最左匹配原则 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

最左匹配原則

最左匹配原則就是指在聯(lián)合索引中,如果你的 SQL 語句中用到了聯(lián)合索引中的最左邊的索引,那么這條 SQL 語句就可以利用這個聯(lián)合索引去進行匹配。例如某表現(xiàn)有索引(a,b,c),現(xiàn)在你有如下語句:

select * from t where a=1 and b=1 and c =1;     #這樣可以利用到定義的索引(a,b,c),用上a,b,c

select * from t where a=1 and b=1;     #這樣可以利用到定義的索引(a,b,c),用上a,b

select * from t where b=1 and a=1;     #這樣可以利用到定義的索引(a,b,c),用上a,c(mysql有查詢優(yōu)化器)

select * from t where a=1;     #這樣也可以利用到定義的索引(a,b,c),用上a

select * from t where b=1 and c=1;     #這樣不可以利用到定義的索引(a,b,c)

select * from t where a=1 and c=1;     #這樣可以利用到定義的索引(a,b,c),但只用上a索引,b,c索引用不到

也就是說通過最左匹配原則你可以定義一個聯(lián)合索引,但是使得多中查詢條件都可以用到該索引。
值得注意的是,當(dāng)遇到范圍查詢(>、<、between、like)就會停止匹配。也就是:

select * from t where a=1 and b>1 and c =1; #這樣a,b可以用到(a,b,c),c索引用不到 

這條語句只有 a,b 會用到索引,c 都不能用到索引。這個原因可以從聯(lián)合索引的結(jié)構(gòu)來解釋。

但是如果是建立(a,c,b)聯(lián)合索引,則a,b,c都可以使用索引,因為優(yōu)化器會自動改寫為最優(yōu)查詢語句

select * from t where a=1 and b >1 and c=1;  #如果是建立(a,c,b)聯(lián)合索引,則a,b,c都可以使用索引
#優(yōu)化器改寫為
select * from t where a=1 and c=1 and b >1;

這也是最左前綴原理的一部分,索引index1:(a,b,c),只會走a、a,b、a,b,c 三種類型的查詢,其實這里說的有一點問題,a,c也走,但是只走a字段索引,不會走c字段。

另外還有一個特殊情況說明下,select * from table where a = '1' and b > ‘2’ and c='3' 這種類型的也只會有 a與b 走索引,c不會走。

像select * from table where a = '1' and b > ‘2’ and c='3' 這種類型的sql語句,在a、b走完索引后,c肯定是無序了,所以c就沒法走索引,數(shù)據(jù)庫會覺得還不如全表掃描c字段來的快。

以index (a,b,c)為例建立這樣的索引相當(dāng)于建立了索引a、ab、abc三個索引。一個索引頂三個索引當(dāng)然是好事,畢竟每多一個索引,都會增加寫操作的開銷和磁盤空間的開銷。

最左匹配原則的原理

最左匹配原則都是針對聯(lián)合索引來說的,所以我們可以從聯(lián)合索引的原理來了解最左匹配原則。

我們都知道索引的底層是一顆 B+ 樹,那么聯(lián)合索引當(dāng)然還是一顆 B+ 樹,只不過聯(lián)合索引的健值數(shù)量不是一個,而是多個。構(gòu)建一顆 B+ 樹只能根據(jù)一個值來構(gòu)建,因此數(shù)據(jù)庫依據(jù)聯(lián)合索引最左的字段來構(gòu)建 B+ 樹。
例子:假如創(chuàng)建一個(a,b,c)的聯(lián)合索引,那么它的索引樹是這樣的:


該圖就是一個形如(a,b,c)聯(lián)合索引的 b+ 樹,其中的非葉子節(jié)點存儲的是第一個關(guān)鍵字的索引 a,而葉子節(jié)點存儲的是三個關(guān)鍵字的數(shù)據(jù)。這里可以看出 a 是有序的,而 b,c 都是無序的。但是當(dāng)在 a 相同的時候,b 是有序的,b 相同的時候,c 又是有序的。
通過對聯(lián)合索引的結(jié)構(gòu)的了解,那么就可以很好的了解為什么最左匹配原則中如果遇到范圍查詢就會停止了。以 select * from t where a=5 and b>0 and c =1; #這樣a,b可以用到(a,b,c),c不可以 為例子,當(dāng)查詢到 b 的值以后(這是一個范圍值),c 是無序的。所以就不能根據(jù)聯(lián)合索引來確定到低該取哪一行。

總結(jié)

在 InnoDB 中聯(lián)合索引只有先確定了前一個(左側(cè)的值)后,才能確定下一個值。如果有范圍查詢的話,那么聯(lián)合索引中使用范圍查詢的字段后的索引在該條 SQL 中都不會起作用。
值得注意的是,in= 都可以亂序,比如有索引(a,b,c),語句 select * from t where c =1 and a=1 and b=1,這樣的語句也可以用到最左匹配,因為 MySQL 中有一個優(yōu)化器,他會分析 SQL 語句,將其優(yōu)化成索引可以匹配的形式,即 select * from t where a =1 and a=1 and c=1

為什么要使用聯(lián)合索引

1、減少開銷。建一個聯(lián)合索引(col1,col2,col3),實際相當(dāng)于建了(col1),(col1,col2),(col1,col2,col3)三個索引。每多一個索引,都會增加寫操作的開銷和磁盤空間的開銷。對于大量數(shù)據(jù)的表,使用聯(lián)合索引會大大的減少開銷!

2、覆蓋索引。對聯(lián)合索引(col1,col2,col3),如果有如下的sql: select col1,col2,col3 from test where col1=1 and col2=2。那么MySQL可以直接通過遍歷索引取得數(shù)據(jù),而無需回表,這減少了很多的隨機io操作。減少io操作,特別的隨機io其實是dba主要的優(yōu)化策略。所以,在真正的實際應(yīng)用中,覆蓋索引是主要的提升性能的優(yōu)化手段之一。

3、效率高。索引列越多,通過索引篩選出的數(shù)據(jù)越少。有1000W條數(shù)據(jù)的表,有如下sql:select from table where col1=1 and col2=2 and col3=3,假設(shè)假設(shè)每個條件可以篩選出10%的數(shù)據(jù),如果只有單值索引,那么通過該索引能篩選出1000W10%=100w條數(shù)據(jù),然后再回表從100w條數(shù)據(jù)中找到符合col2=2 and col3= 3的數(shù)據(jù),然后再排序,再分頁;如果是聯(lián)合索引,通過索引篩選出1000w10% 10% *10%=1w,效率提升可想而知!

使用索引優(yōu)化查詢問題:
1、創(chuàng)建單列索引還是多列索引?
如果查詢語句中的where、order by、group 涉及多個字段,一般需要創(chuàng)建多列索引,比如:

select * from user where nick_name = 'ligoudan' and job = 'dog';
2、多列索引的順序如何選擇?
一般情況下,把選擇性高德字段放在前面,比如:
查詢sql:

select * from user where age = '20' and name = 'zh' order by nick_name;
這時候如果建索引的話,首字段應(yīng)該是age,因為age定位到的數(shù)據(jù)更少,選擇性更高。
但是務(wù)必注意一點,滿足了某個查詢場景就可能導(dǎo)致另外一個查詢場景更慢。
3、避免使用范圍查詢
很多情況下,范圍查詢都可能導(dǎo)致無法使用索引。
4、盡量避免查詢不需要的數(shù)據(jù)

explain select * from user where job like '%ligoudan%';
explain select job from user where job like '%ligoudan%';
同樣的查詢,不同的返回值,第二個就可以使用覆蓋索引,第一個只能全表遍歷了。
5、查詢的數(shù)據(jù)類型要正確

explain select * from user where create_date >= now();
explain select * from user where create_date >= '2020-05-01 00:00:00';
第一條語句就可以使用create_date的索引,第二個就不可以。

總結(jié)

以上是生活随笔為你收集整理的MYSQL | 最左匹配原则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。