explain慢查询SQL调优exists的实战

 更新时间:2023年12月02日 14:49:13   作者:苏三说技术  
这篇文章主要介绍了explain慢查询SQL调优exists的实战,经过两次优化SQL语句之后,慢SQL的性能显著提升了,耗时从8s优化到了0.7s,现在拿出来给大家分享一下,希望对你会有所帮助

最近我在公司优化了一些慢查询SQL,积累了一些SQL调优的实战经验。这篇文章从实战的角度出发,给大家分享一下如何做SQL调优。

经过两次优化之后,慢SQL的性能显著提升了,耗时从8s优化到了0.7s

现在拿出来给大家分享一下,希望对你会有所帮助。

1 案发现场

前几天,我收到了一封报警邮件,提示有一条慢查询SQL。

我打开邮件查看了详情,那条SQL大概是这样的:

SELECT count(*)
FROM spu s1
WHERE EXISTS (
 SELECT *
 FROM sku s2
  INNER JOIN mall_sku s3 ON s3.sku_id = s2.id
 WHERE s2.spu_id = s1.id
  AND s2.status = 1
  AND NOT EXISTS (
   SELECT *
   FROM supplier_sku s4
   WHERE s4.mall_sku_id = s3.id
    AND s4.supplier_id = 123456789
    AND s4.status = 1
  )
)

这条SQL的含义是统计id=123456789的供应商,未发布的spu数量是多少。

这条SQL的耗时竟然达标了8s,必须要做优化了。

我首先使用explain关键字查询该SQL的执行计划,发现spu表走了type类型的索引,而sku、mall_sku、supplier_sku表都走了ref类型的索引。

也就是说,这4张表都走了索引

不是简单的增加索引,就能解决的事情。

那么,接下来该如何优化呢?

2 第一次优化

这条SQL语句,其中两个exists关键字引起了我的注意。

一个exists是为了查询存在某些满足条件的商品,另一个not exists是为了查询出不存在某些商品。

这个SQL是另外一位已离职的同事写的。

不清楚spu表和sku表为什么不用join,而用了exists。

我猜测可能是为了只返回spu表的数据,做的一种处理。如果join了sku表,则可能会查出重复的数据,需要做去重处理。

从目前看,这种写性能有瓶颈。

因此,我做出了第一次优化。

使用join + group by组合,将sql优化如下:

SELECT count(*) FROM
(
  select s2.spu_id from spu s1
  inner join from sku s2
  inner join mall_sku s3 on s3.sku_id=s2.id
  where s2.spu_id=s1.id and s2.status=1
  and not exists 
  (
     select * from supplier_sku s4
     where s4.mall_sku_id=s3.id
     and s4.supplier_id=...
  )
  group by s2.spu_id
) a

文章中有些相同的条件省略了,由于spu_id在sku表中是增加了索引的,因此group by的性能其实是挺快的。

这样优化之后,sql的执行时间变成了2.5s

性能提升了3倍多,但是还是不够快,还需要做进一步优化。

3 第二次优化

还有一个not exists可以优化一下。

如果是小表驱动大表的时候,使用not exists确实可以提升性能。

但如果是大表驱动小表的时候,使用not exists可能有点弄巧成拙。

这里exists右边的sql的含义是查询某供应商的商品数据,而目前我们平台一个供应商的商品并不多。

于是,我将not exists改成了not in。

sql优化如下:

SELECT count(*) FROM
(
  select s2.spu_id from spu s1
  inner join from sku s2
  inner join mall_sku s3 on s3.sku_id=s2.id
  where s2.spu_id=s1.id and s2.status=1
  and s3.id not IN 
  (
     select s4.mall_sku_id 
     from supplier_sku s4
     where s4.mall_sku_id=s3.id
     and s4.supplier_id=...
  )
  group by s2.spu_id
) a

这样优化之后,该sql的执行时间下降到了0.7s。

之后,我再用explain关键字查询该SQL的执行计划。

发现spu表走了全表扫描,sku表走了eq_ref类型的索引,而mall_sku和supplier_sku表走了ref类型的索引。

可以看出,有时候sql语句走了4个索引,性能未必比走了3个索引好。

多张表join的时候,其中一张表走了全表扫描,说不定整个SQL语句的性能会更好,我们一定要多测试。

exists和not exists常用示例说明

1.查询a表在b表中存在数据

相当于sql中in操作。

select * from a where exists (select 1 from b where a_id=a.id )

以上sql等价于下面的sql

select * from a where id in (select a_id from b)

2.查询a表在b表中不存在数据

相当于sql中not in操作。

select * from a where not exists (select 1 from b where a_id=a.id )

以上sql等价于下面的sql

select * from a where id not in (select a_id from b)

3.查询时间最新记录

以下sql查询同一id内的c_date最近的记录。

SELECT * FROM c t1
   WHERE NOT EXISTS(select * from c where id = t1.id and c_date>t1.c_date)

分析:子查询中,先看id = 1 的情形,只有当t1.c_date 取最大值时,没有返回结果,因为是NOT EXISTS关键字,所以Where条件成立,返回符合条件的查询结果

4.exists替代distinct剔除重复数据

例如下面sql

SELECT distinct a.id,a.name from a, b WHERE a.id=b.a_id;

使用exists提出重复,等价于上面的sql

select id,name from a where exists (select 1 from b where a_id=a.id );

分析:RDBMS 核心模块将在子查询的条件一旦满足后,立即返回结果,所以自带去重

总结

说实话,SQL调优是一个比较复杂的问题,需要考虑的因素有很多,有可能需要多次优化才能满足要求。

到此这篇关于explain慢查询SQL调优exists的实战的文章就介绍到这了,更多相关慢查询SQL调优exists内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 数据库学习建议之提高数据库速度的十条建议

    数据库学习建议之提高数据库速度的十条建议

    很多网站的重要信息都是保存在数据库中,用户通过提交访问数据库来获取用户信息。如果数据库速度非常的快,有助于节省服务器的资源,那么如何优化数据库的速度呢,下面通过此篇文章一起学习数据库学习建议之提高数据库速度的十条建议
    2015-11-11
  • 数据库的三级模式和两级映射介绍

    数据库的三级模式和两级映射介绍

    在这里大家一定要注意三级模式中的概念模式对应的是数据库设计的逻辑模型,而不是概念模型(E-R模型),一定不要弄混了
    2012-10-10
  • 数据库之SQL注入原理以及过程的简单介绍

    数据库之SQL注入原理以及过程的简单介绍

    这篇文章主要介绍了数据库之SQL注入原理以及过程的简单介绍,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • 使用Sqlyog远程连接数据库报错解决方案

    使用Sqlyog远程连接数据库报错解决方案

    大家好,本篇文章主要讲的是使用Sqlyog远程连接数据库报错解决方案,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Doris实时多维分析的解决方案详解

    Doris实时多维分析的解决方案详解

    这篇文章主要为大家介绍了Doris实时多维分析的解决方案详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 详解SQLite中的查询规划器

    详解SQLite中的查询规划器

    这篇文章主要介绍了详解SQLite中的查询规划器,SQLite是一个开源的嵌入式数据库,需要的朋友可以参考下
    2015-07-07
  • 详解 MapperScannerConfigurer之sqlSessionFactory注入方式

    详解 MapperScannerConfigurer之sqlSessionFactory注入方式

    这篇文章主要介绍了详解 MapperScannerConfigurer之sqlSessionFactory注入方式的相关资料,需要的朋友可以参考下
    2017-04-04
  • SQL Server不存在或访问被拒绝问题的解决

    SQL Server不存在或访问被拒绝问题的解决

    最近做一个项目(Asp.net+Sql Server 2000),在原来开发的机器上运行没有任何问题.但当我在另外一台机器上调试程序(本机调试)的时候,总出现“SQL Server不存在或访问被拒绝”。相信在任何一个搜索网站输入这样的检索词,一定会获得n多的页面。
    2008-04-04
  • JetBrains DataGrip安装和使用的详细教程

    JetBrains DataGrip安装和使用的详细教程

    日常开发中少不了各种可视化数据库管理工具。本文介绍另一个十分好用且强大的工具:DataGrip。具有一定的参考价值,感兴趣的可以了解一下
    2021-09-09
  • 解决MongoVUE的Collections数据不显示的问题

    解决MongoVUE的Collections数据不显示的问题

    这篇文章主要介绍了MongoVUE的Collections数据不显示的解决方法 ,需要的朋友可以参考下
    2017-05-05

最新评论