服务器之家:专注于服务器技术及软件下载分享
分类导航

Mysql|Sql Server|Oracle|Redis|MongoDB|PostgreSQL|Sqlite|DB2|mariadb|Access|数据库技术|

服务器之家 - 数据库 - Mysql - MYSQL Left Join优化(10秒优化到20毫秒内)

MYSQL Left Join优化(10秒优化到20毫秒内)

2022-01-25 17:24幽寒冰魄 Mysql

在实际开发中,相信大多数人都会用到join进行连表查询,但是有些人发现,用join好像效率很低,而且驱动表不同,执行时间也不同。那么join到底是如何执行的呢,本文就详细的介绍一下

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

【功能背景】

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

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

【原始的SQL】

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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】

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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优化内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/cdnsa/article/details/93609503

延伸 · 阅读

精彩推荐
  • MysqlMySQL服务器连接过程浅析

    MySQL服务器连接过程浅析

    这篇文章主要介绍了MySQL服务器连接过程浅析,本文从源码分析了MySQL服务器的连接过程,需要的朋友可以参考下 ...

    MYSQL教程网3482020-04-30
  • MysqlWindows 下 MySQL 8.X 的安装教程

    Windows 下 MySQL 8.X 的安装教程

    这篇文章主要介绍了Windows 下 MySQL 8.X 的安装教程,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下...

    杨小格子5342020-12-15
  • Mysqlmysql 5.7.21 解压版安装配置方法图文教程

    mysql 5.7.21 解压版安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 5.7.21 解压版安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    如妖5102019-07-15
  • Mysql如何设置mysql允许外网访问

    如何设置mysql允许外网访问

    本篇文章是对设置mysql允许外网访问的解决方法进行了详细的分析介绍,需要的朋友参考下 ...

    MYSQL教程网4142020-04-02
  • MysqlMySQL全局共享内存介绍

    MySQL全局共享内存介绍

    这篇文章主要介绍了MySQL全局共享内存介绍,全局共享内存则主要是 MySQL Instance(mysqld进程)以及底层存储引擎用来暂存各种全局运算及可共享的暂存信息...

    MYSQL教程网3852020-04-24
  • MysqlWindows Server 2003下修改MySQL 5.5数据库data目录

    Windows Server 2003下修改MySQL 5.5数据库data目录

    这篇文章主要介绍了Windows Server 2003下修改MySQL 5.5数据库data目录,需要的朋友可以参考下 ...

    OSYUNWEI3132020-06-04
  • MysqlMySQL数据分析存储引擎示例讲解

    MySQL数据分析存储引擎示例讲解

    这篇文章主要为大家介绍了MySQL数据分析关于存储引擎的示例讲解,搞懂存储引擎会对大家在数据分析方面有很大的帮助,有需要的朋友可以借鉴参考下...

    数据分析与统计学之美11182021-11-25
  • MysqlMysql提权的多种姿势汇总

    Mysql提权的多种姿势汇总

    这篇文章主要给大家介绍了关于Mysql提权的多种姿势,姿势包括写入Webshell、UDF提权以及MOF提权,文中通过示例代码介绍的非常详细,需要的朋友可以参考下...

    大鹏东南飞11062021-09-13