欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

MySQL聯(lián)合索引與最左匹配原則的實現(xiàn)

 更新時間:2023年12月11日 09:09:44   作者:王廷云的博客  
最左匹配原則在我們MySQL開發(fā)過程中和面試過程中經(jīng)常遇到,為了加深印象和理解,我在這里把MySQL的最左匹配原則詳細的講解一下,感興趣的可以了解一下

前言:

最左匹配原則在我們 MySQL 開發(fā)過程中和面試過程中經(jīng)常遇到,為了加深印象和理解,我在這里把 MySQL 的最左匹配原則詳細的講解一下,包括它的原理以及是否導致索引失效的場景。

在講解 MySQL 的最左匹配原則之前,我們需要了解一下 MySQL 的聯(lián)合索引(也稱復合索引),因為最左匹配原則是在聯(lián)合索引的基礎上產(chǎn)生的,沒有聯(lián)合索引就沒有最左匹配原則這個概念。

一、聯(lián)合索引

1、什么是聯(lián)合索引

我們知道,單值索引指的是只使用一個字段作為索引字段的索引,而聯(lián)合索引則是使用多個字段來共同構(gòu)建成一個索引:

KEY idx_abc (a, b, c);

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

2-1、減少開銷

建一個聯(lián)合索引 (a, b, c),實際上相當于建了 (a)、(a, b)、(a, b, c) 三個索引。這樣我們就不需要創(chuàng)建 (a)、(b)、(c) 三個單值索引了。我們知道,每多一個索引,都會增加數(shù)據(jù)庫寫操作的開銷和磁盤空間的開銷,對于大量數(shù)據(jù)的表,使用聯(lián)合索引會大大的減少開銷!

2-2、覆蓋索引

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

2-3、提高效率

聯(lián)合索引的字段越多,通過索引篩選出的數(shù)據(jù)越少。假如有 1000W 條數(shù)據(jù)的表,有如下 sql: select * from table where a=1 and b=2 and c=3,假設每個條件可以篩選出 10% 的數(shù)據(jù),如果只有單值索引,那么通過該索引能篩選出 1000W * 10% = 100w 條數(shù)據(jù),然后再回表從 100w 條數(shù)據(jù)中找到符合 b=2 and c=3 的數(shù)據(jù),然后再排序,再分頁。

但如果是聯(lián)合索引,則通過索引直接篩選出的數(shù)據(jù)為:1000w * 10% * 10% * 10% = 1w,這效率的提升可想而知!

二、最左匹配原則

1、最左匹配原則的規(guī)則

在聯(lián)合索引當中,索引匹配時:最左字段優(yōu)先,以最左邊的字段為起點任何連續(xù)的字段索引都能匹配上,如果遇到范圍查詢 (>、<、between、like) 時就會停止匹配。

2、索引是否生效的場景

是否滿足最左匹配原則是衡量聯(lián)合索引命中與否的依據(jù)。存在的場景比較多,假設我們創(chuàng)建了以 a, b, c 三個字段的聯(lián)合索引 idx_abc(a, b, c),下面我們分別展開討論索引是否失效的場景。

2-1、全字段全值匹配

索引的全部字段都在查找條件當中,并且都是使用 = 進行全值匹配的情況下,索引是命中生效的:

select * from table_name where a = '1' and b = '2' and c = '3'
select * from table_name where b = '2' and a = '1' and c = '3'
select * from table_name where c = '3' and b = '2' and a = '1'
......

雖然 where 子句幾個搜索條件順序調(diào)換了,但不影響查詢結(jié)果,這是由于 MySQL 的查詢優(yōu)化器會自動調(diào)整 where 子句的條件順序以使用適合的索引,所以 MySQL 不存在 where 子句的順序問題而造成索引失效。

2-2、從左到右按順序匹配

select * from table_name where a = '1'
select * from table_name where a = '1' and b = '2'
select * from table_name where a = '1' and b = '2' and c = '3'

只要是按照聯(lián)合索引創(chuàng)建的字段從左到右的順序依次使用,不管使用其中多少個字段,都會命中索引。

2-3、缺失最左邊的字段

select * from table_name where  b = '2' 
select * from table_name where  c = '3'
select * from table_name where  b = '1' and c = '3' 

這種缺失了最左邊 a 字段的情況就是違背最左匹配原則的典型例子,結(jié)果就是沒有用到索引(索引失效)。

因為缺失了最左邊的字段,導致索引數(shù)據(jù)結(jié)構(gòu) B+ 樹不知道第一步該查哪個節(jié)點,從而需要去全表掃描了。在建立搜索樹的時候 a 就是第一個比較因子,必須要先根據(jù) a 來搜索,進而才能往后繼續(xù)查詢 b 和 c。

2-4、缺失中間的字段

假如去掉中間的字段,保留最左邊和右邊的字段(就是我們說的索引字段不連續(xù)):

select * from table_name where a = '1' and c = '3' 

結(jié)果就是只用到了 a 列的索引,而 b 列和 c 列都沒有用到。

因為在這種情況下進行數(shù)據(jù)檢索時,B+ 樹可以用 a 來指定第一步的搜索方向,但由于下一個字段 b 的缺失,所以只能先把 a = 1 的數(shù)據(jù)主鍵 ID 都找出來,然后通過查到的主鍵 ID 回表查詢相關行,再去匹配 c 值的數(shù)據(jù)了。當然,這至少把 a = 1 的數(shù)據(jù)篩選出來了,總比直接全表掃描好多了

2-5、匹配范圍值

出現(xiàn)匹配范圍值的情況可能比較復雜或難以理解,但我們只需要牢記最左匹配原則的規(guī)則:遇到范圍查詢 (>、<、between、like) 時就會停止匹配

比如下面這種情況:

select * from table_name where  a = 1 and b > 3 and c = 'mm';

這種情況下,由于 a 是等值匹配,所以 B+ 樹走完 a 索引之后 b 還是有序的,但走完 b 索引之后,由于 b 是范圍匹配,所以此時 c 已經(jīng)是無序的了,最終只使用了 (a, b) 兩個索引(由于此時 c 就沒法走索引,所以優(yōu)化器只能根據(jù) a, b 得到數(shù)據(jù)的主鍵 ID 回表查詢,最終影響了執(zhí)行效率)。

再比如下面的情況:

select * from table_name where  a > 1 and b > 1
select * from table_name where  a > 1 and a < 3 and b > 1;

當多個列同時進行范圍查找時,只有對索引最左邊的那個列進行范圍查找才用到 B+ 樹索引,也就是只有 a 用到索引,在 a > 1 和 1 < a < 3 的范圍內(nèi) b 是無序的,所以 b 不能用索引,找到 a 的記錄后,只能根據(jù)條件 b > 1 繼續(xù)逐條過濾。

2-6、like 語句匹配問題

當索引列是字符型,并且使用了 like 語句進行模糊查詢時,如果通配符 % 不出現(xiàn)在開頭,則可以用到索引,否則將會違背了最左匹配原則,而不會使用索引,走的是全表掃描:

select * from table_name where a like 'As%';   //走索引查詢
select * from table_name where a like '%As';   //全表查詢
select * from table_name where a like '%As%';  //全表查詢

我們先了解一下字符型字段的比較規(guī)則:當列是字符型的話,它的比較規(guī)則是先比較字符串的第一個字符,第一個字符小的那個字符串就比較小,如果兩個字符串第一個字符相同,那就再比較第二個字符,依次類推。

所以,如果通配符 % 出現(xiàn)在開頭,B+ 樹則無法進行比較匹配,進而導致索引失效。

3、解決文件排序的問題

當我們對查詢的數(shù)據(jù)進行 order by 排序時,一般情況下,我們是先把數(shù)據(jù)記錄加載到內(nèi)存中,再用一些排序算法,比如快速排序,歸并排序等在內(nèi)存中對這些記錄進行排序。但有時候查詢的結(jié)果集太大不能在內(nèi)存中進行排序時,需要暫時借助磁盤空間存放中間結(jié)果,排序操作完成后再把排好序的結(jié)果返回客戶端。Mysql 把這種在磁盤上進行排序的方式稱為文件排序Filesort)。

文件排序是非常慢非常耗性能的,但如果 order by 子句用到了索引列,就有可能避免文件排序的問題:

select * from table_name order by a, b, c limit 10;

因為 B+ 樹索引本身就是按照上述規(guī)則排序的,準確來說就是:索引是有序的,所以得到的結(jié)果集已經(jīng)排好序了,不用再進行額外的排序操作。

注意:order by 的子句后面的字段順序也必須按照索引字段的順序給出,不能顛倒順序(MySQL 不會自動調(diào)整排序字段的順序)。

下面這種就是因為顛倒順序而沒有使用索引的情況:

select * from table_name order by b, c, a limit 10;

下面這種是用到部分索引的情況:

select * from table_name order by a limit 10;
select * from table_name order by a, b limit 10;

下面這種情況,由于聯(lián)合索引左邊列為常量,后邊的列排序可以用到索引:

select * from table_name where a =1 order by b, c limit 10;

 到此這篇關于MySQL聯(lián)合索引與最左匹配原則的實現(xiàn)的文章就介紹到這了,更多相關MySQL聯(lián)合索引與最左匹配原則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • mysql錯誤處理之ERROR 1786 (HY000)

    mysql錯誤處理之ERROR 1786 (HY000)

    最近一直在mysql的各個版本直接徘徊,這中間遇到了各種各樣的錯誤,將已經(jīng)處理完畢的幾個錯誤整理了一下,分享給大家,首先我們來看看錯誤提示 ERROR 1786 (HY000)
    2014-07-07
  • mysql存儲過程事務管理簡析

    mysql存儲過程事務管理簡析

    本文將提供了一個絕佳的機制來定義、封裝和管理事務,需要的朋友可以參考下
    2012-11-11
  • MySQL 觸發(fā)器的使用和理解

    MySQL 觸發(fā)器的使用和理解

    這篇文章主要介紹了MySQL 觸發(fā)器的使用和理解,幫助大家更好的理解和學習使用MySQL,感興趣的朋友可以了解下
    2021-02-02
  • 使用mysql workbench自動生成ER圖的實現(xiàn)步驟

    使用mysql workbench自動生成ER圖的實現(xiàn)步驟

    MySQL Workbench是一款專為MySQL設計的ER/數(shù)據(jù)庫建模工具,它是著名的數(shù)據(jù)庫設計工具DBDesigne4的繼任者,可以通過MySQL Workbench設計和創(chuàng)建新的數(shù)據(jù)庫圖示,本文給大家介紹了使用mysql workbench自動生成ER圖的實現(xiàn)步驟,需要的朋友可以參考下
    2024-06-06
  • MySQL導入數(shù)據(jù)權限問題的解決

    MySQL導入數(shù)據(jù)權限問題的解決

    本文主要介紹了MySQL導入數(shù)據(jù)權限問題的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-03-03
  • asp.net 將圖片上傳到mysql數(shù)據(jù)庫的方法

    asp.net 將圖片上傳到mysql數(shù)據(jù)庫的方法

    圖片通過asp.net上傳到mysql數(shù)據(jù)庫的方法
    2009-06-06
  • MySQL高效模糊搜索之內(nèi)置函數(shù)locate instr position find_in_set使用詳解

    MySQL高效模糊搜索之內(nèi)置函數(shù)locate instr position find_in_set使用詳解

    在MySQL中一般進行模糊搜索都是使用LIKE配合通配符進行查詢的,在性能上一定的影響,下面給大家分享MYSQL自帶的內(nèi)置模糊搜索函數(shù),除最后一個外其它三個性能上要比Like快些
    2018-09-09
  • mysql詳細分析講解子查詢的使用

    mysql詳細分析講解子查詢的使用

    子查詢指一個查詢語句嵌套在另一個查詢語句內(nèi)部的查詢,這個特性從 MySQL 4.1開始引入,在SELECT子句中先計算子查詢,子查詢結(jié)果作為外層另一個查詢的過濾條件,查詢可以基于一個表或者多個表
    2022-04-04
  • ERROR 1862 (HY000): Your password has expired. To log in you must change it using a .....

    ERROR 1862 (HY000): Your password has expired. To log in you

    當你在安裝 MySQL過程中,通過mysqld --initialize 初始化 mysql 操作后,生成臨時密碼后,沒有直接進行 MySQL連接,中途重啟服務或者重啟機器等,導致密碼失效問題,怎么處理呢,感興趣的朋友一起看看吧
    2019-11-11
  • MySQL中基本的用戶和權限管理方法小結(jié)

    MySQL中基本的用戶和權限管理方法小結(jié)

    這篇文章主要介紹了MySQL中基本的用戶和權限管理方法小結(jié),是MySQL入門學習中的基礎知識,需要的朋友可以參考下
    2015-08-08

最新評論