您好,登錄后才能下訂單哦!
這篇文章主要介紹了MySQL細數發生索引失效的情況實例分析的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇MySQL細數發生索引失效的情況實例分析文章都會有所收獲,下面我們一起來看看吧。
首先了解一下索引的存儲結構,知道了索引的存儲結構,才方便我們更好地理解索引失效的問題。
索引的存儲結構跟MySQL的存儲引擎有關,存儲引擎的不同采用的結構也會不同。
MySQL默認的存儲引擎InnoDB采用B+Tree作為索引的數據結構,在創建表時,InnoDB會默認創建一個主鍵索引,這是一個聚簇索引,其他索引都屬于二級索引。
MyISAM存儲引擎在創建表時,默認是用的是B+樹索引。
雖然和InnoDB一樣都支持B+樹索引,但是他們存儲數據的方式不同;
InnoDB是聚簇索引(B+樹索引的葉子結點保存數據本身)
MyISAM是非聚集索引(B+樹的葉子結點保存數據的物理地址)
如下圖所示:
InnoDB存儲引擎可以分為【聚簇索引】和【二級索引】,它們的區別在于聚簇索引的葉子結點存放的是實際數據,所有完整的數據都存放在聚簇索引的葉子結點,二級索引的葉子結點存放的是主鍵值。
在使用二級索引字段作為查詢條件,查詢數據在聚簇索引上的時候,
會先根據條件在二級索引上找到對應的葉子結點得到主鍵值,
再根據主鍵值去聚簇索引上找到對應的葉子結點然后查詢到對應的數據,
這個過程叫回表
使用二級索引作為查詢條件,查詢的數據在二級索引的葉子結點上的時候,那么只需找到二級索引的B+樹對應的葉子結點,讀取數據,這個過程叫覆蓋索引
上面這些查詢條件都用到了索引列,但并不表示用到索引列索引就一定會生效,我們再來看一看索引失效的情況
使用左或左右模糊查詢的時候,也就是like "%張"
或like "%張%"
這兩種模糊查詢方式都會導致索引失效
因為B+樹是根據索引值進行排列的,前綴不確定的時候可能是,“小張”,"二張"之類的所有的情況,就只能通過全表掃描的方式來查詢
例如:SELECT * FROM sys_user WHERE LENGTH(user_id) = 3 ;
因為索引保存的是索引字段的原始值,而不是經過函數計算后的值,所以使用函數的時候就不會走索引了
不過從MySQL8.0開始,索引特性增加了函數索引,也就是針對該函數計算后的值建立一個索引,這樣就可以通過掃描索引來查詢數據了;
alter table t_user add key idx_name_length ((length(name)));
例如:select * from sys_user where user_id+1 =3;
但是如果是SELECT * FROM sys_user WHERE user_id = 1+1 ;
這樣的不在索引字段上進行計算,就又會走索引了
原因跟對索引使用函數差不多,索引保存的是索引字段的原始值,而不是運算后的值,所以無法走索引
這里的phone
字段是二級索引,且是varchar類型的
使用整型作為查詢參數的時候,執行計劃中type為ALL,也就是通過全表掃描查詢的,但如果是字符串類型,還是走索引查詢的
我們再看一個例子
這里user_id
是bigint類型,但是使用字符串作為查詢參數還是走了索引的
為什么第一個例子導致了索引失效,而第二個不會呢?
這里就要了解一下MySQL的字符轉換規則了,看是數字轉字符串,還是字符串轉數字
我們可以用select "10">9
來測試一下
如果是數字轉字符串,那么就相當于select "10">"9"
結果應該是0
如果是字符串轉數字,那么就相當于select 10>9
,結果是1
在MySQL中的執行結果如下:
這就說明,MySQL在遇到數字與字符串的比較的時候,會自動把字符串轉換為數字,然后進行比較
也就是說,在第一個例子中
SELECT * FROM sys_user WHERE phone = 18200000000 ;
相當于
SELECT * FROM sys_user WHERE CAST(phone AS UNSIGNED) = 18200000000 ;
這就在索引字段上使用了函數,所以導致索引失效
而在第二個例子中
SELECT * FROM sys_user WHERE user_id = "1" ;
相當于
SELECT * FROM sys_user WHERE user_id = CAST("1" AS UNSIGNED) ;
函數式作用在查詢參數上的,并沒有作用在索引字段上,所以還是走索引的
多個普通字段組合在一起創建的索引叫做聯合索引(組合索引)
在使用聯合索引的時候,一定要注意順序問題,聯合索引的使用需要遵循最左匹配原則,也就是按照最左優先的方式進行索引匹配。
例如,創建了一個(a,b,c)
聯合索引,那么如果查詢條件是一下幾種,就可以匹配上聯合索引
where a = 1
where a = 1 and b = 2
where a = 1 and b = 2 and c = 3
需要注意的是,因為有查詢優化器,所以a字段在where子句中的順序不重要
但是必須要有a字段,如果像下面幾種,因為不符合最左匹配原則,就無法匹配上聯合索引,聯合索引就會失效:
where b = 2
where c = 3
where b = 2 and c = 3
還有一個比較特殊的查詢條件:where a = 1 and c = 3
在MySQL5.5的話,前面的a 會走索引,在聯合索引找到主鍵值,然后回表,到主鍵索引讀取數據行,然后在比對c字段的值
在MySQL5.6之后,有一個索引下推的功能,
下推就是將部分上層(服務層)負責的事情,交給了下層(引擎層)處理
存儲引擎直接在聯合索引里按照c=3過濾,按照過濾后的數據在進行回表掃描,減少了回表的次數,從而提升了性能
在執行計劃中Extra = Using index condition就表示使用了索引下推
聯合索引不遵循最左匹配原則的原因:在聯合索引中,數據按照第一列索引進行排序,第一列數據相同時,才會按照第二列進行排序,以此類推,所以直接使用第二列進行查詢的時候,聯合索引就會失效
where子句中or的條件列有不是索引列會導致索引失效
例如:下圖中id是索引列,email不是索引列,從執行計劃來看,進行了全文掃描并沒有使用到索引
因為or關鍵字只滿足一個條件就可以,因此只要有一個列不是索引列,其他索引列也就沒有意義了,就會進行全表掃描
在email列上建立索引之后,可以看到執行計劃中使用到了兩個索引
type = index_merge表示對id 和email都進行了掃描,然后進行了合并
關于“MySQL細數發生索引失效的情況實例分析”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“MySQL細數發生索引失效的情況實例分析”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。