字符集轉(zhuǎn)換導(dǎo)致的索引失效
引言
2021年春節(jié)后的某個(gè)忙(mo)碌(yu)的下午,旁邊的劉哥(老江湖,從業(yè)5年+)突然發(fā)出了一聲嘆息:“哎,mysql 出bug了,有索引不走”。
作為一個(gè)熱心的人,我立即說到:“是不是,對(duì)索引字段做了函數(shù)操作”。
劉哥沉思了2秒,略有玩味的小眼神看了看我,慢慢說道:“溫兄,常規(guī)的情況,對(duì)索引字段做函數(shù)操作,或者 字符串與數(shù)字比較造成的隱式轉(zhuǎn)換,這次的SQL都不涉及”。
我一聽頓時(shí)來了興趣,略帶興奮的跟劉哥說:“劉哥,您發(fā)SQL,我也研究下”。
劉哥略有無奈的看了看我后,依舊把SQL發(fā)給了我:
SELECT
*
FROM
oc_order oo
JOIN orders_detail od ON oo.order_id = od.order_id
不過須臾(近20分鐘),我便查明了原因,裝作大師的模樣,一字一句的說到:”這是,字符集隱式轉(zhuǎn)換問題”
劉哥聽后,百度了下,直拍大腿,“對(duì)對(duì),怎么把這個(gè)給忘了”。
定位問題
1.首先執(zhí)行explain,查看執(zhí)行計(jì)劃
explain
SELECT
*
FROM
oc_order oo
JOIN orders_detail od ON oo.order_id = od.order_id

確實(shí)被驅(qū)動(dòng)表orders_detail 沒走索引
第一個(gè)表就是驅(qū)動(dòng)表,后邊的都是被驅(qū)動(dòng)表,會(huì)從驅(qū)動(dòng)板取出數(shù)據(jù)作為參數(shù),到被驅(qū)動(dòng)表查詢匹配的記錄。
2. 查看被驅(qū)動(dòng)表的索引
SHOW INDEX FROM test.orders_detail;

3.查看字段字符集
SELECT
COLUMN_NAME,
character_set_name,
collation_name
FROM
INformation_schema.`COLUMNS`
WHERE
TABLE_NAME = 'oc_order'
AND COLUMN_NAME = 'order_id';

SELECT
COLUMN_NAME,
character_set_name,
collation_name
FROM
INformation_schema.`COLUMNS`
WHERE
TABLE_NAME = 'orders_detail'
AND COLUMN_NAME = 'order_id';

Mysql字符集說明
utf8m4是utf8超集,utf8,與utf8mb4會(huì)比較,utf8會(huì)轉(zhuǎn)換為utf8mb4。推薦:Java面試寶典
驗(yàn)證
調(diào)整SQL語句,將oc_orders的order_id強(qiáng)制轉(zhuǎn)換為utf8。
explain
SELECT
*
FROM
oc_order oo
JOIN orders_detail od ON CONVERT ( oo.order_id USING UTF8 ) = od.order_id

查看執(zhí)行計(jì)劃,確實(shí)走了索引
解決方式
調(diào)整SQL語句
SELECT
*
FROM
oc_order oo
JOIN orders_detail od ON CONVERT ( oo.order_id USING UTF8 ) = od.order_id
調(diào)整字符集一致,建議
總結(jié)
可能不走索引的3種情況
對(duì)索引字段做函數(shù)操作
隱式類型轉(zhuǎn)換,字符串與數(shù)字比較,字符串會(huì)轉(zhuǎn)換為數(shù)字
隱式字符集轉(zhuǎn)換,utf8m4是utf8超集,utf8,與utf8mb4會(huì)比較,utf8會(huì)轉(zhuǎn)換為utf8mb4.
