文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

MYSQLLeftJoin优化(10秒优化到20毫秒内)

2024-04-02 19:55

关注

结合工作中的内容和大家分享一次Left Jon优化的过程,希望能给同学们新的思路。

【功能背景】

    我们需要按照用户订单号和商户号统计出购买的商品数量和售后的商品数量。涉及到的表和关系见下图:

很不幸工程师在起初进行表结构设计的时候没有在商户订单表中记录下购买的商品总数,在商户订单的售后单中也没记录下售后的商品数量。

【原始的SQL】


select 
  o.no,s_order.no,sum(s_item.count),sum(after_sale_item.count)
  from 
  buyer_order o 
  left join seller_order s_order on o.id = s_order.buyer_order_id 
  left join seller_order_item s_item on s_order.id = s_item.seller_order_id
  left join seller_order_after_sale after_sale on s_order.id = after_sale.seller_order_id
  left join seller_order_after_sale_item after_sale_item on after_sale.id = after_sale_item.after_sale_id
where o.add_time >='2019-05-01'
group by
  o.id,s_order.id
order by 
  o.id
limit 0,10

以上SQL几个关键字段都使用了索引。  

【原始的SQL分析】

这是一条很常规的SQL,逻辑上也没什么毛病

这条SQL中有较多的连接查询,如果随着售后单的增加,连接的数据就会更多

将符合条件的数据都加载到内存后按照 order.id,s_order.id 进行分组统计,如果有100W的数据会怎样?如果你用代码去实现这么一段统计你会怎么做?

将统计完的数据再按照 order.id 进行排序,取出前10条数据。

从以上的SQL发现需要将符合条件的所有的数据加载到内存后要进行分组,统计,排序,最后再进行分页。我们能不能减少数据的加载数量呢?能不能减少数据库CPU的使用量,能不能先取少量的数据再统计呢?

基于以上的问题,我们进行了优化

【分析步骤】

作为旁观者一开始不了解我们功能需要输出什么样的数据,所以我们一开始要了解每张表存储的是什么样的数据,彼此之间的关系是什么。

我们忘记原来的SQL是什么样的,按照我们需要的数据,再次重新的思考,不要再陷入原来的SQL的漩涡中。

针对上面提出的问题,如何减少数据的加载?能不能先分页数据,再对分页的数据进行单独的统计呢?

那么我们是不是需要对group by进行优化,我们要想办法先分页

大家是否想到了一些方法?

【优化后的SQL】


select 
  o.id,o.no,s_order.no,
  (select sum(sot.count) from seller_order so 
    left join seller_order_item sot on so.id = sot.seller_order_id 
        where so.id =s_order.id ),
  (select sum(osat.count) from seller_order_after_sale osa 
    left join seller_order_after_sale_item osat on osa.id = osat.after_sale_id
        where osa.seller_order_id = s_order.id )
  from 
  buyer_order o 
  left join seller_order s_order on o.id = s_order.buyer_order_id 
where o.addTime >='2019-05-01'
order by 
  o.id
limit 0,10

【优化的SQL分析】

  1. 很直观的发现,我们把group by去掉了,因为按照 order.id,s_order.id 分组,实际只对 buyer_order和seller_order表进行连接,逻辑上是一样的进行了分组。
  2. group by不使用的话我们就减少了CPU对数据分组的处理,而且我们只连接主要的表数据,减少了加载到内存中的数据。
  3. 以上的操作就完成了我们之前说的先对数据分页。我们取出了10条数据。
  4. 接着我们再对10条数据的销售出去的商品数量和售后的数量进行统计
  5. 这时候大家发现,我们其实只对分页出来的10条数据进行统计,原来是将所有的数据分组统计后取10条。可以发现我们这样操作大大减少了对数据的统计处理。我们只需要统计我们需要的数据。

以上优化的效果可能远远超出大家的想象。

实际工作中连表的数比我们例子中的要多,未优化的SQL在执行未分页的时候发现一共有70万的数据,我们分页取出10条数据花了10+秒以上的时间,数据量不大但是大部分的时间都消耗在了分组和数据统计,大家可以试着写一段代码对这些数据进行分组和统计,就能明白其中的复杂性。

而实际上无论取出10条和全部取出,时间基本上一样的(不考虑IO),因为先进行了统计。

优化后的SQL,加载到内存中只有2万左右的数据,而且不进行统计,先取出10条数据,然后再对10条数据进行统计,逻辑上比之前的简单多了。优化后的SQL执行时间在20毫秒以内。

其实如果在订单表和售后表都记录了对应的数量,连表数还要少,还不需要进行子查询。有时候设计表的时候还是需要考虑一下统计的需要。

到此这篇关于MYSQL Left Join优化(10秒优化到20毫秒内)的文章就介绍到这了,更多相关MYSQL Left Join优化内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯