《MySQL tips:隐式类型转换与隐式字符编码转换对查询效率的影响》
維護一個交易系統,交易記錄表tradelog包含交易流水號(tradeid)、交易員id(operator)、交易時間(t_modified)等字段。
create table 'tradelog' ('id' int(11) not null,'tradeid' varchar(32) default null,'operator' int(11) default null,'t_modified' datetime default null,primary key ('id'),key 'tradeid' ('tradeid'),key 't_modified' ('t_modified') ) engine = InnoDB default charset = utf8mb4;隱式類型轉換
select * from tradelog where tradeid = 110717;交易編號tradeid字段上本身就有索引。但是explain這條語句后顯示,這條語句走的時全表掃描。
tradeid 的字段類型是varchar(32),而輸入的參數卻是整型,所以需要做類型轉換
字符串與數字做比較的話,將字符串轉換成數字
所以之前的語句被轉換成:
這個會觸發規則:對索引字段做函數操作,優化器會放棄走樹搜索功能。
如果我們的語句是如下的:
此時不會觸發規則。因為字符串和數字比較,會將字符串轉換成數字。現在字符串在比較符右邊,只會把右邊轉換成數字,所以不會發生轉換,所以仍然走樹搜索。
隱式字符編碼轉換
假設系統里有表trade_detail,用于記錄交易細節。
我們往交易日志表tradelog和交易詳情表trade_detail這兩個表里插入一些數據。
調用該sql語句:
select d.* from tradelog l,trade_detail d where d.tradeid = l.tradeid and l.id = 2;其執行步驟為:
1、根據id在tradelog表里找到L2這一行
2、從L2中取出tradeid字段的值
3、根據tradeid值到trade_detail表中查找條件匹配的行。該過程是通過遍歷主鍵索引的方式,一個一個地判斷tradeid地值是否匹配。
這里的第3步不符合我們的預期,因為trade_detail里tradeid字段是有索引的,我們本來是希望通過使用tradeid索引能夠快速定位到等值的行。但是這里顯然不是這樣做的。
這是因為兩個表的字符集不同,一個是utf8,一個是utf8mb4,所以做表連接查詢的時候用不上關聯字段的索引。
將執行步驟的第三步單獨拎出來改成SQL語句:
$L2.tradeid.value的字符集是utf8mb4;
utf8mb4是utf8的超集,所以當這兩個類型的字符串在做比較的時候,MySQL內部的操作是先將utf8轉換成utf8mb4字符集,再做比較。
也相當于:
這就會觸發:對索引字段做函數操作,優化器會放棄樹搜索功能。
這就是不同字符集連接查詢,關聯字段不走索引的原因。
總結
以上是生活随笔為你收集整理的《MySQL tips:隐式类型转换与隐式字符编码转换对查询效率的影响》的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红楼梦多少钱啊?
- 下一篇: 《MySQL——查询长时间不返回的三种原