工作中我们经常用到多个left join去关联其他表查询结果,但是随着数据量的增加,一个表的数据达到百万级别后,这种普通的left join查询将非常的耗时。

举个例子:

    现在porder表有 1000W数据,其他关联的表数据都很少,因为条件的限制必须要关联3个表,正常的逻辑就是这样写,但是我们在数据库执行的时候会发现这样的SQL非常耗时,而且此时才 limit 800  这样的SQL怎么能让用户受得了呢?

select p.*,b.supplier,t.type,c.org   from porder p 
        left JOIN brand b on p.supplier = b.supplier_id and b.mark = 0
        left JOIN purchase c on p.org = c.id and c.mark = 0
        left JOIN type t on c.category = t.type_id and t.mark = 0 
        WHERE p.nark = 0 ORDER BY p.id desc limit 800,500;

    通过查询SQL优化方面的知识,发现一种比较好的优化方案:

select p.*,b.supplier,t.type,c.org from
        (select po.id from porder po where po.mark = 0 order by po.id desc limit 800000,500) a
        inner join porder p on a.id = p.id and p.mark = 0
        left JOIN brand b on p.supplier = b.supplier_id and b.mark = 0
        left JOIN purchase c on p.org = c.id and c.mark = 0
        left JOIN type t on c.category = t.type_id and t.mark = 0;

    我们可以先将数据量最大表的满足条件的ID查询出来,创建临时表,再用这个临时表去关联这个表本身以及其他表。limit80W 也就1S时间。

SQL分析:

   我们可以使用 explain 查看上面2种SQL的执行计划。第一种SQL的执行计划中通过 row 和extra 都可以看出非常差,row几乎为全部扫描。

   优化后的SQL通过 row 和extra 都可以看出都是很好的状态,row的数据是第一种的 1%。相当于提升了 100倍。

   执行计划中的id列的数值越大,执行权就越高。id列的值相等的,就从上之下依次执行。明白了这一点,我们就可以再分析SQL了。

   数据库先执行了 select po.id from porder po where po.mark = 0 order by po.id desc limit 800000,500 这段SQL,将查询出的有效id(满足条件的id)放在了临时表a中,然后表a再与其他的表匹配查询。

  (注:优先执行的SQL不参与后面的表匹配。这里要理解,不然单独看执行计划,你会纳闷为何row列上a表中数值小,而id列为2的表(po) row列的数值也很大。

          你也可以拆分SQL。优先执行的SQL单独拿出来执行,将查询到的结果当作查询条件,传给普通的 left join 中的where条件里面,即 in(), in的里面不要写SQL查询,必须是明确的数值!)

PS:我只是提供方法,具体的原理,大家可以上网查一查。数据库有一种叫驱动表的概念,大家可以了解下。或许对于理解这种方法更方便!

  注:这个优化后的SQL在执行 limit1000000,**  的时候效率也就下降了,大概4S钟以上。所以这个SQL也是有极限的,对于分页查询等等,如果数据量超过100W 要注意!

希望有大神,能在SQL上能有更高的突破,有方法的,希望大家一起分享,一起学习。谢谢~

  补:为了应对超过百万级别的查询或者导出,SQL优化暂时没有好的办法,但是我们可以在传参上做文章。

比如分页查询时,每页展示20条数据,首页查询时,我们可以得到首页最后一条数据的ID (起名:lastId)(按ID排序,降序),当点击第2页时,我们可以将 lastId 作为参数传入分页查询的SQL中。这样分页时就加上了一个条件,就是 ID<lastId (按ID排序,降序)。

limit也可以优化成  limit 20, 这样优化后,因为limit 不再是 limit xxx,20 ,这样数据库在扫描满足条件的数据时,就会从此ID往后扫描,且扫描到满足条件的20条后,就不会再多扫描,大大减少了扫描的数据量,自然也就提升了效率。

参考:https://www.cnblogs.com/tianzong/p/10552182.html

MySQL-数据库多表关联查询太慢,如何进行SQL语句优化的更多相关文章

  1. 项目总结04:SQL批量导入数据:将具有多表关联的Excel数据,通过sql语句脚本的形式,导入到数据库

    将具有多表关联的Excel数据,通过sql语句脚本的形式,导入到数据库 写在前面:本文用的语言是java:数据库是MySql: 需求:在实际项目中,经常会被客户要求,做批量导入数据:一般的简单的单表数 ...

  2. Python操作Mysql数据库——多表组合查询

    前面我们介绍了单张表的查询,包括模糊查询.分组.排序.各种筛选条件等等操作,在实际应用中,查询的数据往往不止局限在一张表里,通常需要多张表在一起进行组合查询,今天我们将会对Mysql当中的多张有关联的 ...

  3. ORACLE数据库多表关联查询效率问题解决方案

    最近在做项目中遇到多表关联查询排序的效率问题(5张以上40W+数据的表),查询一次大概要20多秒,经过一番苦思冥想,处理方案如下: 1.软件设计初期,需要一对一关联的表应该设计在一张大表里,这样虽然字 ...

  4. mysql三张表关联查询

    三张表,需要得到的数据是标红色部分的.sql如下: select a.uid,a.uname,a.upsw,a.urealname,a.utel,a.uremark, b.rid,b.rname,b. ...

  5. MySql数据库转设计文档(mysql-font工具和sql语句导出)

    一.工具导出 1.使用的是MySQL-Front工具,这个工具使用非常方便,尤其是导出数据的时候,几百万的数据一两分钟就导完了,推荐使用. MySQL-Front下载(只有3.93M):http:// ...

  6. mysql数据库技术1——基本的增删查改的sql语句

    1.数据库语言的分类 DDL:数据库定义语言 data Definition language 用于创建.修改.和删除数据库内的数据结构,如: 1:创建和删除数据库(CREATE DATABASE | ...

  7. MySQL在大数据、高并发场景下的SQL语句优化和"最佳实践"

    本文主要针对中小型应用或网站,重点探讨日常程序开发中SQL语句的优化问题,所谓“大数据”.“高并发”仅针对中小型应用而言,专业的数据库运维大神请无视.以下实践为个人在实际开发工作中,针对相对“大数据” ...

  8. MySQL数据库--创建表,查询

    MySQL创建表: 表(一)Student (学生表): CREATE TABLE `Student` ( `sno` ) DEFAULT NULL, `sname` ) DEFAULT NULL, ...

  9. 关于MySql数据库设计表与查询耗时分析

    本地建一张表persons,使用脚本插入了1000万条数据 下面比较几种查询方法的耗时(查询9000000到9000005这中间5条数据) 查询结果: 1: SELECT * FROM test.pe ...

随机推荐

  1. UltraSoft - Alpha - Scrum Meeting 3

    Date: Apr 15th, 2020. 会议内容为 贡献分确定与进度汇报. Scrum 情况汇报 进度情况 组员 负责 昨日进度 后两日任务 CookieLau PM.后端 学习前后端分离技术的项 ...

  2. UltraSoft - Beta - Scrum Meeting 3

    20200519会议纪要 Date: May 19th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 暂无 Liuzh 前端 暂无 Kkkk 前端 完成了前端 ...

  3. 2021.9.13考试总结[NOIP模拟52]

    T1 路径 考虑每一位的贡献,第$i$位每$2^i$个数会变一次,那么答案为$\sum_{i=1}^{log_2n} \frac{n}{2^i}$. $code:$ 1 #include<bit ...

  4. 快速了解XML

    1. XML 定义 可扩展标记语言,标准通用标记语言的子集,简称XML.是一种用于标记电子文件使其具有结构性的标记语言. 2. XML 展示 如下是一个xml的标记展示,XML 是不作为的XML 被设 ...

  5. 攻防世界 杂项15.János-the-Ripper

    下载附件并解压,我用的是WinHex打开,发现是PK开头,并且文件中包含一个flag.txt文件,应该就是我们所需要的flag. 把下载的附件改后缀为.zip,确实有我们需要的flag,打开后需要密码 ...

  6. opencv学习(一)——图像入门

    图像入门 一.读取图像 在opencv中使用cv.imread(filename, flags)函数读取图像.filename参数表示读取图像的路径.读取图像的路径应完整给出,且不能含有中文,否则在调 ...

  7. Linux&C网络编程————“聊天室”

    从上周到现在一直在完成最后的项目,自己的聊天室,所以博客就没怎么跟了,今天晚上自己的聊天室基本实现,让学长检查了,也有好些bug,自己还算满意,主要实现的功能有: 登录注册 附近的人(服务器端全部在线 ...

  8. LeetCode 重排链表 OPPO笔试

    重排链表 几个关键点: 1. 双指针(快慢指针找中点)(用于反转后一部分) 2. 反转后一部分 (reverse函数) 3. 合并链表 合并的时候在笔试的时候想了一种比我之前想的简单的方法 从slow ...

  9. 学好Python不加班系列之SCRAPY爬虫框架的使用

    scrapy是一个爬虫中封装好的一个明星框架.具有高性能的持久化存储,异步的数据下载,高性能的数据解析,分布式. 对于初学者来说还是需要有一定的基础作为铺垫的学习.我将从下方的思维导图中进行逐步的解析 ...

  10. Python基础(dict与set)

    #和list比较,dict有以下几个特点: #查找和插入的速度极快,不会随着key的增加而变慢: #需要占用大量的内存,内存浪费多. #dict1 = {'傻狗1':100,'傻狗2':200,'傻狗 ...