MySQL实战45讲Day17----为什么某些SQL语句逻辑相同,性能却差异巨大

一、条件字段函数操作: ?1、如果对字段做了函数计算,就用不上索引了。 ?2、如果对字段做了函数计算,MySQL无法再使用索引快速定位功能,而只能使用全索引扫描。 ?3、如果对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就决定放弃走树搜索功能(B+树提供的这个快速定位能力,来源于同一层兄弟节点的有序性)。 二、隐式类型转换: ?1、where条件里面的两个参数的类型不同时,一般需要进行类型转换,隐性的调用了函数。 ?2、在MySQL中,字符串和数字做比较的话,是将字符串转换成数字。 三、隐式字符编码转换: ?1、从A表中取b字段,再去C表里查询匹配字段。因此,我们把A称为驱动表,把C称为被驱动表,把b称为关联字段。 ?2、where条件里面的两个参数的字符集不同时,一般需要进行字符集转换,隐性的调用了函数。 ?3、连接过程中要求在被驱动表的索引字段上加函数操作,是直接导致对被驱动表做全表扫描的原因。 注意: 1、

假设表trade_detail采用的字符集是utf8,表tradelog采用的字符集是utf8mb4。 语句一:mysql> select * from trade_detail where tradeid=$L2.tradeid.value; --$L2.tradeid.value的字符集是utf8mb4。 语句二:select * from trade_detailwhere CONVERT(traideid USING utf8mb4)=$L2.tradeid.value; 语句三:select operator from tradelogwhere traideid =$R4.tradeid.value; --$R4.tradeid.value的字符集是utf8 语句四:select operator from tradelogwhere traideid =CONVERT($R4.tradeid.value USING utf8mb4);

语句一和语句二是等效的,可以看出把输入的字符串转成utf8mb4字符集,进行了函数操作,所以只能走全索引扫描。
语句三和语句四是等效的,可以看出这里的CONVERT函数是加在输入参数上的,这样就可以用上被驱动表的traideid索引。
2、对于下面语句的优化方法:
mysql> select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2;

方法一:把trade_detail表上的tradeid字段的字符集也改成utf8mb4,这样就没有字符集转换的问题了。
mysql> alter table trade_detail modify tradeid varchar(32) CHARACTER SET utf8mb4 default null;

【MySQL实战45讲Day17----为什么某些SQL语句逻辑相同,性能却差异巨大】方法二:如果数据量比较大, 或者业务上暂时不能做这个DDL的话,就只能修改SQL语句了。
mysql> select d.* from tradelog l , trade_detail d where d.tradeid=CONVERT(l.tradeid USING utf8) and l.id=2;

    推荐阅读