MySQL隐式转换案例一则
Posted bisal(Chen Liu)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL隐式转换案例一则相关的知识,希望对你有一定的参考价值。
隐式转换,可以说是关系型数据库SQL优化中很隐秘的问题,之前碰到过很多和他相关的案例,
《Oracle、SQL Server和MySQL的隐式转换异同》
数据和云的这篇文章《SQL优化——隐式字符编码转换》则介绍了mysql中因为字符集不同导致的隐式转换的问题。
MySQL中我们知道,
如果对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能。
隐式类型转换也会导致放弃走树搜索。
因为类型转换等价于在条件字段上使用了函数,例如,
假设tradeid字段有索引,且为varchar类型,
mysql> select * from tradelog where tradeid=110717;
等价于,
mysql> select * from tradelog where CAST(tradid AS signed int) = 110717;
下面来看看隐式字符编码转换导致的一个慢SQL,业务上有个SQL执行需要1.31秒,
看执行计划,
从执行计划分析看出问题出在r表也就是h_merge_result_new_indicator表全表扫描,查看该表的表结有联合索引。但是联合索引范围后会失效,于是打算新建一个联合索引,
查看预新建联合索引的字段选择性,
结合选择性来看,
create index idx_hmrni on h_merge_result_new_indicator(keyName,module,BATCH_NO);
创建后,再次看执行计划依然无效,
查看表结构,
另外3个表结构其中有2个utf8mb4,1个utf8,
字符集utf8mb4是utf8的超集,所以当这两个类型的字符串在做比较的时候,MySQL内部的操作是,先将utf8字符串转成utf8mb4字符集,再做比较。因此,
这部分会转换后再与h_merge_result_new_indicator关联。优化就只需要将字符集编码转为utf8再和h_merge_result_new_indicator关联就能用上索引,
再看查询只需要0.02秒了,
但是还有个问题,如上执行计划key_len是606=(100*3+3)+(100*3+3)。就是说,没有用上BATCH_NO字段上的索引,我们知道索引少一个字段,占用会减少,不会太臃肿。因此,联合索引只需要包含(keyName,module),
drop index idx_hmrni on h_merge_result_new_indicator;
create index idx_hmrni on h_merge_result_new_indicator(keyName,module);
对索引字段做函数操作,无论是显式,还是隐式,都会破坏索引值的有序性,进而影响优化器的判断,这对Oracle和MySQL都是相通的。
因此,在开发阶段,以及审核阶段,对这些问题的规避和挖掘,还是值得关注的,投入产出比,还是比较可观的。
近期更新的文章:
《最近碰到的问题》
文章分类和索引:
以上是关于MySQL隐式转换案例一则的主要内容,如果未能解决你的问题,请参考以下文章