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