MySQL实战 | 18 为什么这些SQL语句逻辑相同,性能却差

2019-05-14  本文已影响0人  hoxis

在 MySQL 中,有很多看上去逻辑相同,但性能却差异巨大的 SQL 语句。对这些语句使用不当的话,就会不经意间导致整个数据库的压力变大。

案例一:条件字段函数操作

假设有如下语句,并且字段 t_modified 上有索引:

mysql> select count(*) from tradelog where month(t_modified)=7;

那么这条语句会很快地返回数据吗?

答案是否定的。

对索引字段做函数操作,可能会破坏索引值的有序性,因此优化器就会放弃走树索引。

这里,由于加了 month() 函数操作,MySQL 无法再使用索引快速定位功能,而只能使用全索引扫描。

语句优化:

mysql> select count(*) from tradelog where
    -> (t_modified >= '2016-7-1' and t_modified<'2016-8-1') or
    -> (t_modified >= '2017-7-1' and t_modified<'2017-8-1') or 
    -> (t_modified >= '2018-7-1' and t_modified<'2018-8-1');

案例二:隐式类型转换

有如下语句:

mysql> select * from tradelog where tradeid=110717;

tradeid 字段是 varchar(32) 类型的,而对比的参数是整数,所有就需要做类型转换。

1、数据类型转换的规则是什么?

select "10" > 9 的结果:

① 如果结果是 1,那么就是将字符串转换成数字
② 如果结果是 0,那么就是将数字转换成字符串

如果是将字符串转换成数字,那么上面的语句对应的就是:

mysql> select * from tradelog where  CAST(tradid AS signed int) = 110717;

其实就出发了案例一里面的规则,对字符串索引进行了函数操作,优化器就会放弃树搜索的功能,进行全表搜索。

案例三:隐式字符编码转换

如下语句:

mysql> select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2; /* 语句 Q1*/

如果表 tradelog(utf8) 和表 trade_detail(utf8mb4) 的字符集不同,那么 d.tradeid=l.tradeid 条件也会导致全表扫描。

字符集 utf8mb4 是 utf8 的超集,所以当这两个类型的字符串在做比较的时候,MySQL 内部的操作是,先把 utf8 字符串转成 utf8mb4 字符集,再做比较。

同样,触发了案例一中的条件。


你的关注是对我最大的鼓励!

关注本公众号,后台回复「2018」即可获取传智播客 2018 最新 Python 和 Java 教程。

公众号提供CSDN资源免费下载服务!


上一篇下一篇

猜你喜欢

热点阅读