mysql筆記系列 十六 索引列失效的原因

2021-10-04 02:55:08 字數 1951 閱讀 3886

列上加了索引,但是實際執行的時候依然很慢。

1.索引列上加了函式

t_modified列為索引

where t_modified=『2018-7-1』 索引生效

where month(t_modified)=7 索引無效

首先,所有的函式都是在server層執行的,儲存引擎只負責取數。

因此,where month(t_modified)=7的過程是,先從儲存引擎取出乙個數,然後service層執行month(t_modified)函式,求出值,並判斷是否等於7。

如果不等於,就取下一條。

這樣是沒辦法走索引的, 因為儲存引擎並不知道什麼樣的資料month()之後會等於7,這裡面並沒有任何有序性可言,比如說即使2018-9-10 month之後不等於7,儲存引擎也無法根據這個結果來縮小查詢的範圍,因此就只能全表掃瞄。

例如你是要找2018-10-12的話,就可以判斷出這個值是在比2018-9-10大的範圍區間,因此可以進一步縮小範圍。

b+ 樹提供的這個快速定位能力,**於同一層兄弟節點的有序性

而對索引欄位做函式操作,可能會破壞索引值的有序性,因此優化器就決定放棄走 樹搜尋功能。

放棄 樹搜尋功能,不代表就放棄了這個索引,比如說這裡,即使不使用樹搜尋,那麼會判斷可以使用哪些索引,t_modified列索引或者主鍵索引,

這裡依然會選擇t_modified列索引,只是掃瞄了這個索引的全部值。 這個就是全索引掃瞄,並沒有用到索引的快速定位功能。

注意:優化器即使在不改變有序性的函式,也不會考慮使用索引

explain select * from t_order_detail where id+1=198

因此需要注意 不要在索引列使用任何函式,不管是否會改變有序性

那如果 select * from t_order_detail where order_code=substr(『511502029215』,3,4) ,這個依然會走索引,

因為執行器先將函式值計算出來了,substr(『511502029215』,3,4) 其實是乙個常量,等效於1502

2.隱式轉換

例如:索引列欄位型別是 varchar(32), 但是輸入的值是整數,實際上在執行的時候,會做轉換。

轉換會將字串轉為整數

走索引select * from t_order_detail where order_code=『512001002559』

不走索引

select * from t_order_detail where order_code=512001002559

等效於select * from t_order_detail where cast(order_code as signed int)=512001002559

觸發了對索引列做函式操作。

3.編碼轉換

當字段值的編碼不同的時候

where a.order_code=b.order_code

如果a和b的order_code列字符集不同,比如說乙個是utf8 乙個是utf8mb4

會將a的編碼轉為utf8mb4

where convert(a.order_code using utf8mb4)=b.order_code

遇到這種情況的解決方案

1.改字段的字符集編碼,但是資料量很大的情況下 影響比較大

2.改sql,改關聯順序 比如說 where b.order_code=a.order_code ,改變join的順序,此時效果等於

where b.order_code= convert(a.order_code using utf8mb4)

3.改sql 自己手動轉換

where a.order_code= convert(b.order_code using utf8) 這裡手動將b的字符集編碼從utf8mb4 轉為了utf8

這篇的總結:

對索引欄位做函式操作,可能會破 壞索引值的有序性,因此優化器就決定放棄走樹搜尋功能。

學習筆記 mysql索引(四) 多列索引

多列索引有兩個意思,乙個是在多個列上建立乙個索引,另乙個意思是在多個列上分別建立索引。比較直觀能夠想到,如果是在多個列上建立乙個索引,那麼如果where條件裡正好又是這些列,那麼將獲得較好的效能。如果分別建立索引,where中又有多個分別建立的索引的列,那mysql優化器將如何處理呢?explain...

mysql多列索引 MySQL的多列索引

什麼是索引?索引用來快速地尋找那些具有特定值的記錄,所有mysql索引都以b 樹的形式儲存。如果沒有索引,執行查詢時mysql必須從第乙個記錄開始掃瞄整個表的所有記錄,直至找到符合要求的記錄。表裡面的記錄數量越多,這個操作的代價就越高。如果作為搜尋條件的列上已經建立了索引,mysql無需掃瞄任何記錄...

mysql 3列索引 mysql之多列索引

mysql的多列索引是經常會遇到的問題,怎樣才能有效命中索引,是本文要 的重點。多列索引使用的btree,也就是平衡二叉樹。簡單來說就是排好序的快速索引方式。它的原則就是要遵循左字首索引。多個索引從左邊往右都使用上,才能使用到整個多列索引。下面我先建立乙個簡單的表做實驗 create table t...