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

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

作者: hoxis | 来源:发表于2019-05-14 03:19 被阅读0次

    在 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资源免费下载服务!


    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/ioxjaqtx.html