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_detail  where CONVERT(traideid USING utf8mb4)=$L2.tradeid.value; 

语句三:select operator from tradelog  where traideid =$R4.tradeid.value;         --$R4.tradeid.value的字符集是utf8
语句四:select operator from tradelog  where 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;

方法二:如果数据量比较大, 或者业务上暂时不能做这个DDL的话,就只能修改SQL语句了。

mysql> select d.* from tradelog l , trade_detail d where d.tradeid=CONVERT(l.tradeid USING utf8) and l.id=2; 

你可能感兴趣的:(MySQL实战45讲Day17----为什么某些SQL语句逻辑相同,性能却差异巨大)