(二)为什么这些sql语句逻辑相同,性能却差异巨大?

1.条件字段函数操作

现在已经记录了从2016年初到2018年底的所有数据,运营部门有一个需求是,要统计发
生在所有年份中7月份的交易记录总数。这个逻辑看上去并不复杂,你的SQL语句可能会这么
写:

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

根据上图的索引规则显示,这条sql查询会降低性能,因为当month=7时,数据库索引库蒙逼了,不知所谓了,

但是你要随着数据库的索引库的信息去改变一下sql语句:

> 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');

性能会提升好多,一方面是索引库直接影响了查询性能,但是更重要的是

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

在这个例子里,放弃了树搜索功能,优化器可以选择遍历主键索引,也可以选择遍历索引
t_modified,优化器对比索引大小后发现,索引t_modified更小,遍历这个索引比遍历主键索引
来得更快。因此最终还是会选择索引t_modified。

MySQL的优化器确实有“偷懒”的嫌疑,即使简单地把where id+1=1000改写成where id=1000-1就
能够用上索引快速查找,也不会主动做这个语句重写。

2.隐式类型转换

mysql> select * from tradelog where tradeid=110717;

两边的类型不一样引发类型转换,一旦发生类型转换了,数据库就不再根据索引查找数据了,就需要走全盘扫描了;

对于优化器来说,我们上边写的sql语句相当于

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

改善:

select * from tradelog where id="83126";

3.隐士字符编码转换

这张图是两张表的数据根据id查询数据

正如下面的sql语句:

select d.* from tradelog l, trade_detail d where d.tradeid=l.tradeid and l.id=2;

此sql语句,是先遍历id ,然后拿着id再去取第二张表的对应,获取第二张表的的id,然后发现获取的id不是想要的数据,所以便是id.value   ,进行了第四步操作,然后发生了数据编码格式转换。

改善:

发布了241 篇原创文章 · 获赞 31 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_40406929/article/details/102785072