字符編碼,不走索引的元兇之一

引言

2021年春節後的某個忙(mo)碌(yu)的下午,旁邊的劉哥(老江湖,從業5年+)突然發出了一聲嘆息:“哎,mysql 出bug了,有索引不走”。

作爲一個熱心的人,我立即說到:“是不是,對索引字段做了函數操作”。

劉哥沉思了2秒,略有玩味的小眼神看了看我,慢慢說道:“溫兄,常規的情況,對索引字段做函數操作,或者 字符串與數字比較造成的隱式轉換,這次的SQL都不涉及”。

我一聽頓時來了興趣,略帶興奮的跟劉哥說:“劉哥,您發SQL,我也研究下”。

劉哥略有無奈的看了看我後,依舊把SQL發給了我:

SELECT * FROM oc_order oo join orders_detail od ON oo.order_id =od.order_id 

不過須臾(近20分鐘),我便查明瞭原因,裝作大師的模樣,一字一句的說到:”這是,字符集隱式轉換問題

劉哥聽後,百度了下,直拍大腿,“對對,怎麼把這個給忘了”。

定位問題

1.首先執行explain,查看執行計劃

explain
SELECT * FROM oc_order oo join orders_detail od ON oo.order_id =od.order_id 

確實被驅動表orders_detail 沒走索引

第一個表就是驅動表,後邊的都是被驅動表,會從驅動板取出數據作爲參數,到被驅動表查詢匹配的記錄。

                                                                                                                                                                        --- 非專業術語,溫安適 20210223

2. 查看被驅動表的索引

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會比較,utf8會轉換爲utf8mb4.

驗證

調整SQL語句,將oc_orders的order_id強制轉換爲utf8。

explain
SELECT * FROM oc_order oo join orders_detail od ON convert(oo.order_id USING UTF8) =od.order_id 

查看執行計劃,確實走了索引

解決方式

調整SQL語句

SELECT * FROM oc_order oo join orders_detail od ON convert(oo.order_id USING UTF8) =od.order_id 

調整字符集一致,建議

總結

可能不走索引的3種情況

  1. 對索引字段做函數操作
  2. 隱式類型轉換,字符串與數字比較,字符串會轉換爲數字
  3. 隱式字符集轉換,utf8m4是utf8超集,utf8,與utf8mb4會比較,utf8會轉換爲utf8mb4.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章