设为首页收藏本站
网站公告 | 这是第一条公告
     

 找回密码
 立即注册
缓存时间07 现在时间07 缓存数据 抱怨是一件最没意义的事情,如果实在难以忍受周围的环境,那就暗自努力练好本领,然后跳出那个圈子,早安!

抱怨是一件最没意义的事情,如果实在难以忍受周围的环境,那就暗自努力练好本领,然后跳出那个圈子,早安!

查看: 990|回复: 0

explain慢查询SQL调优exists的实战

[复制链接]

  离线 

TA的专栏

  • 打卡等级:常驻代表
  • 打卡总天数:39
  • 打卡月天数:0
  • 打卡总奖励:502
  • 最近打卡:2025-04-18 00:36:40
等级头衔

等級:晓枫资讯-上等兵

在线时间
0 小时

积分成就
威望
0
贡献
314
主题
276
精华
0
金钱
1437
积分
672
注册时间
2023-2-11
最后登录
2025-5-31

发表于 2025-5-31 06:32:17 | 显示全部楼层 |阅读模式
最近我在公司优化了一些慢查询SQL,积累了一些
  1. SQL调优
复制代码
的实战经验。这篇文章从实战的角度出发,给大家分享一下如何做SQL调优。
经过两次优化之后,慢SQL的性能显著提升了,耗时从
  1. 8s
复制代码
优化到了
  1. 0.7s
复制代码

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

1 案发现场

前几天,我收到了一封报警邮件,提示有一条慢查询SQL。
我打开邮件查看了详情,那条SQL大概是这样的:
  1. SELECT count(*)
  2. FROM spu s1
  3. WHERE EXISTS (
  4. SELECT *
  5. FROM sku s2
  6.   INNER JOIN mall_sku s3 ON s3.sku_id = s2.id
  7. WHERE s2.spu_id = s1.id
  8.   AND s2.status = 1
  9.   AND NOT EXISTS (
  10.    SELECT *
  11.    FROM supplier_sku s4
  12.    WHERE s4.mall_sku_id = s3.id
  13.     AND s4.supplier_id = 123456789
  14.     AND s4.status = 1
  15.   )
  16. )
复制代码
这条SQL的含义是统计id=123456789的供应商,未发布的spu数量是多少。
这条SQL的耗时竟然达标了
  1. 8s
复制代码
,必须要做优化了。
我首先使用
  1. explain
复制代码
关键字查询该SQL的
  1. 执行计划
复制代码
,发现spu表走了type类型的索引,而sku、mall_sku、supplier_sku表都走了ref类型的索引。
也就是说,这4张表都走了
  1. 索引
复制代码

不是简单的增加索引,就能解决的事情。
那么,接下来该如何优化呢?

2 第一次优化

这条SQL语句,其中两个
  1. exists
复制代码
关键字引起了我的注意。
一个
  1. exists
复制代码
是为了查询存在某些满足条件的商品,另一个
  1. not exists
复制代码
是为了查询出不存在某些商品。
这个SQL是另外一位已离职的同事写的。
不清楚spu表和sku表为什么不用join,而用了exists。
我猜测可能是为了只返回spu表的数据,做的一种处理。如果join了sku表,则可能会查出重复的数据,需要做去重处理。
从目前看,这种写性能有瓶颈。
因此,我做出了第一次优化。
使用
  1. join
复制代码
+
  1. group by
复制代码
组合,将sql优化如下:
  1. SELECT count(*) FROM
  2. (
  3.   select s2.spu_id from spu s1
  4.   inner join from sku s2
  5.   inner join mall_sku s3 on s3.sku_id=s2.id
  6.   where s2.spu_id=s1.id and s2.status=1
  7.   and not exists
  8.   (
  9.      select * from supplier_sku s4
  10.      where s4.mall_sku_id=s3.id
  11.      and s4.supplier_id=...
  12.   )
  13.   group by s2.spu_id
  14. ) a
复制代码
文章中有些相同的条件省略了,由于spu_id在sku表中是增加了索引的,因此group by的性能其实是挺快的。
这样优化之后,sql的执行时间变成了
  1. 2.5s
复制代码

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

3 第二次优化

还有一个not exists可以优化一下。
如果是小表驱动大表的时候,使用not exists确实可以提升性能。
但如果是大表驱动小表的时候,使用not exists可能有点弄巧成拙。
这里exists右边的sql的含义是查询某供应商的商品数据,而目前我们平台一个供应商的商品并不多。
于是,我将not exists改成了not in。
sql优化如下:
  1. SELECT count(*) FROM
  2. (
  3.   select s2.spu_id from spu s1
  4.   inner join from sku s2
  5.   inner join mall_sku s3 on s3.sku_id=s2.id
  6.   where s2.spu_id=s1.id and s2.status=1
  7.   and s3.id not IN
  8.   (
  9.      select s4.mall_sku_id
  10.      from supplier_sku s4
  11.      where s4.mall_sku_id=s3.id
  12.      and s4.supplier_id=...
  13.   )
  14.   group by s2.spu_id
  15. ) 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操作。
  1. select * from a where exists (select 1 from b where a_id=a.id )
复制代码
以上sql等价于下面的sql
  1. select * from a where id in (select a_id from b)
复制代码
2.查询a表在b表中不存在数据

相当于sql中not in操作。
  1. select * from a where not exists (select 1 from b where a_id=a.id )
复制代码
以上sql等价于下面的sql
  1. select * from a where id not in (select a_id from b)
复制代码
3.查询时间最新记录

以下sql查询同一id内的c_date最近的记录。
  1. SELECT * FROM c t1
  2.    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
  1. SELECT distinct a.id,a.name from a, b WHERE a.id=b.a_id;
复制代码
使用exists提出重复,等价于上面的sql
  1. select id,name from a where exists (select 1 from b where a_id=a.id );
复制代码
分析:RDBMS 核心模块将在子查询的条件一旦满足后,立即返回结果,所以自带去重

总结

说实话,SQL调优是一个比较复杂的问题,需要考虑的因素有很多,有可能需要多次优化才能满足要求。
到此这篇关于explain慢查询SQL调优exists的实战的文章就介绍到这了,更多相关慢查询SQL调优exists内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
      1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
      2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
      3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:点击这里给我发消息进行删除处理。
      4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
      5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
http://bbs.yzwlo.com 晓枫资讯--游戏IT新闻资讯~~~
严禁发布广告,淫秽、色情、赌博、暴力、凶杀、恐怖、间谍及其他违反国家法律法规的内容。!晓枫资讯-社区
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|晓枫资讯--科技资讯社区 本站已运行

CopyRight © 2022-2025 晓枫资讯--科技资讯社区 ( BBS.yzwlo.com ) . All Rights Reserved .

晓枫资讯--科技资讯社区

本站内容由用户自主分享和转载自互联网,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。

如有侵权、违反国家法律政策行为,请联系我们,我们会第一时间及时清除和处理! 举报反馈邮箱:点击这里给我发消息

Powered by Discuz! X3.5

快速回复 返回顶部 返回列表