《MySQL tips:隐式类型转换与隐式字符编码转换对查询效率的影响》
維護(hù)一個(gè)交易系統(tǒng),交易記錄表tradelog包含交易流水號(hào)(tradeid)、交易員id(operator)、交易時(shí)間(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;隱式類(lèi)型轉(zhuǎn)換
select * from tradelog where tradeid = 110717;交易編號(hào)tradeid字段上本身就有索引。但是explain這條語(yǔ)句后顯示,這條語(yǔ)句走的時(shí)全表掃描。
tradeid 的字段類(lèi)型是varchar(32),而輸入的參數(shù)卻是整型,所以需要做類(lèi)型轉(zhuǎn)換
字符串與數(shù)字做比較的話(huà),將字符串轉(zhuǎn)換成數(shù)字
所以之前的語(yǔ)句被轉(zhuǎn)換成:
這個(gè)會(huì)觸發(fā)規(guī)則:對(duì)索引字段做函數(shù)操作,優(yōu)化器會(huì)放棄走樹(shù)搜索功能。
如果我們的語(yǔ)句是如下的:
此時(shí)不會(huì)觸發(fā)規(guī)則。因?yàn)樽址蛿?shù)字比較,會(huì)將字符串轉(zhuǎn)換成數(shù)字?,F(xiàn)在字符串在比較符右邊,只會(huì)把右邊轉(zhuǎn)換成數(shù)字,所以不會(huì)發(fā)生轉(zhuǎn)換,所以仍然走樹(shù)搜索。
隱式字符編碼轉(zhuǎn)換
假設(shè)系統(tǒng)里有表trade_detail,用于記錄交易細(xì)節(jié)。
我們往交易日志表tradelog和交易詳情表trade_detail這兩個(gè)表里插入一些數(shù)據(jù)。
調(diào)用該sql語(yǔ)句:
select d.* from tradelog l,trade_detail d where d.tradeid = l.tradeid and l.id = 2;其執(zhí)行步驟為:
1、根據(jù)id在tradelog表里找到L2這一行
2、從L2中取出tradeid字段的值
3、根據(jù)tradeid值到trade_detail表中查找條件匹配的行。該過(guò)程是通過(guò)遍歷主鍵索引的方式,一個(gè)一個(gè)地判斷tradeid地值是否匹配。
這里的第3步不符合我們的預(yù)期,因?yàn)閠rade_detail里tradeid字段是有索引的,我們本來(lái)是希望通過(guò)使用tradeid索引能夠快速定位到等值的行。但是這里顯然不是這樣做的。
這是因?yàn)閮蓚€(gè)表的字符集不同,一個(gè)是utf8,一個(gè)是utf8mb4,所以做表連接查詢(xún)的時(shí)候用不上關(guān)聯(lián)字段的索引。
將執(zhí)行步驟的第三步單獨(dú)拎出來(lái)改成SQL語(yǔ)句:
$L2.tradeid.value的字符集是utf8mb4;
utf8mb4是utf8的超集,所以當(dāng)這兩個(gè)類(lèi)型的字符串在做比較的時(shí)候,MySQL內(nèi)部的操作是先將utf8轉(zhuǎn)換成utf8mb4字符集,再做比較。
也相當(dāng)于:
這就會(huì)觸發(fā):對(duì)索引字段做函數(shù)操作,優(yōu)化器會(huì)放棄樹(shù)搜索功能。
這就是不同字符集連接查詢(xún),關(guān)聯(lián)字段不走索引的原因。
總結(jié)
以上是生活随笔為你收集整理的《MySQL tips:隐式类型转换与隐式字符编码转换对查询效率的影响》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 红楼梦多少钱啊?
- 下一篇: 《MySQL——查询长时间不返回的三种原