mysql取締最左匹配原則 最左匹配原則

2021-10-18 15:33:28 字數 2807 閱讀 2222

一、這條sql語句select * from dept where age=12 and name like 'a%',雖然age條件在前,name在後,看似不滿足最左側原則,但這條語句在執行的過程中mysql優化器會將該條語句優化為select * from dept where name like 'a%' and age=12,還是會走聯合索引。

二、怎麼走的索引?為什麼會出現index using condition索引下推,這就要用where條件的提取規則解釋了,我們在執行一條sql時,會將 where 條件拆分為 index key(first key & last key)、index filter 與 table filter,具體怎麼拆分呢,先看下面的定義,然後在以你的sql為例,咱們拆一次。

index key:

用於確定 sql 查詢在索引中的連續範圍(起始點 + 終止點)的查詢條件,被稱之為index key;由於乙個範圍,至少包含乙個起始條件與乙個終止條件,因此 index key 也被拆分為 index first key 和 index last key,分別用於定位索引查詢的起始點以終止點。

index first key:

用於確定索引查詢範圍的起始點;提取規則:從索引的第乙個鍵值開始,檢查其在 where 條件中是否存在,若存在並且條件是 =、>=(like 也算》=),則將對應的條件加入index first key之中,繼續讀取索引的下乙個鍵值,使用同樣的提取規則;若存在並且條件是 >,則將對應的條件加入 index first key 中,同時終止 index first key 的提取;若不存在,同樣終止 index first key 的提取。

index last key:

用於確定索引查詢範圍的終止點,與 index first key 正好相反;提取規則:從索引的第乙個鍵值開始,檢查其在 where 條件中是否存在,若存在並且條件是 =、<=,則將對應條件加入到 index last key 中,繼續提取索引的下乙個鍵值,使用同樣的提取規則;若存在並且條件是 < ,則將條件加入到 index last key 中,同時終止提取;若不存在,同樣終止index last key的提取

index filter:

index filter 用於索引範圍確定後,確定 sql 中還有哪些條件可以使用索引來過濾;提取規則:從索引列的第一列開始,檢查其在 where 條件中是否存在,若存在並且 where 條件僅為 =,則跳過第一列繼續檢查索引下一列,下一索引列採取與索引第一列同樣的提取規則;若 where 條件為 >=、>、=、>、

table filter:

這個就比較簡單了,where 中不能被索引過濾的條件都歸為此中;提取規則:所有不屬於索引列的查詢條件,均歸為 table filter 之中

看到這兒是不是有點暈了,沒事兒,拿你的sql為例子,咱拆一次你就懂了。

sql:select * from dept where age=12 and name like 'a%',

被sql優化器優化後:select * from dept where name like 'a%' and age=12

先提取index first key,沒記住規則上去看下,按照聯合索引(name,age)順序,先看name在不在where裡,ok在,然後看name的條件是否是》或》=(這裡like等價於》=),ok條件符合規則,那麼將name like 'a%'加入index first key,然後繼續按照此規則讀取下一列索引age,age的條件是=,也符合規則,再把age=12也加入index first key,到此index first key提取完成,裡面是name like 'a%',age=12

下一步提取index last key,規則不說了沒記住的話上去看下,還是按照聯合索引順序,先看name,發現name是》=不符合規則,跳過繼續看age,age是=,符合規則,將age加入到index last key,到此index last key也提取完成,裡面是age=12

下一步提取index filter(索引下推的關鍵),按照聯合索引順序,先看name,發現name是》=,觸發規則(若 where 條件為 >=、>、

最後一步提取table filter,由於這個sql沒有用到非索引列,所以table filter為空

好了全部都提取完了,那這些提取出來的東西怎麼用啊?這就要扯到mysql的服務層和引擎層的職責了,咱們上面所說的where提取工作是在mysql服務層完成的,在執行sql時,server層會將這些where條件推送至引擎層,引擎層根據這些條件遍歷索引樹,這裡就有兩個分支了,乙個是5.6版本以前,乙個是5.6之後,先說5.6以前沒有索引下推的時候,是不區分index filter和table filter的,只會將index key推送至引擎層,引擎層根據index key遍歷索引樹確認範圍後,逐條回表,每查一條返回至server層,然後再用index filter和table filter的條件進行過濾,而5.6加入索引下推後,會將index key和index filter一同推送至引擎層,引擎層首先根據index key遍歷索引樹確認範圍,然後再用index filter對範圍進行過濾,最終將過濾後的結果集逐一回表,回表後返回至server層,如果存在table filter,再用table filter進行過濾。

根據上述的規則,你這個sql語句index key:name like 'a%',age = 12,index filter:age=12,所以既會用到索引也會用到索引下推(我認為這裡index filter其實沒起作用,因為index key已經鎖住所有的範圍了),這就是為什麼你的查詢計畫既會出現使用到索引也會出現使用到索引下推了。

以上是我個人愚見,其實按照這些規則,你去試一些sql的時候會發生與規則衝突的情況,比如就你這個sql,index key已經將結果集完全鎖定了,為什麼還會提示用到索引下推,我也在慢慢摸索,相互討論吧。

Mysql最左匹配原則

看了好多部落格,講講自己的理解 索引的底層是一顆b 樹,那麼聯合索引當然還是一顆b 樹,只不過聯合索引的健值數量不是乙個,而是多個。構建一顆b 樹只能根據乙個值來構建,因此資料庫依據聯合索引最左的字段來構建b 樹。例子 假如建立乙個 a,b 的聯合索引,那麼它的索引樹是這樣的 可以看到a的值是有順序...

最左匹配原則

寫在前面 我在上大學的時候就聽說過資料庫的最左匹配原則,當時是通過各大部落格論壇了解的,但是這些部落格的侷限性在於它們對最左匹配原則的描述就像一些數學定義一樣,往往都是列出123點,滿足這123點就能匹配上索引,否則就不能。但是我覺得程式設計不是死記硬背,這個所謂最左匹配原則肯定是有他背後的原理的。...

MySQL索引 最左匹配原則

表結構,有三個字段,分別是id,name,cid create table student id int 11 not null auto increment,name varchar 255 default null,cid int 11 default null,primary key id k...