工作中我们经常用到多个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. [no_code][Alpha]发布声明报告

    项目 内容 2020春季计算机学院软件工程(罗杰 任健) 2020春季计算机学院软件工程(罗杰 任健) 作业要求 发布声明 我们在这个课程的目标是 设计出一个OCR表单处理软件 这个作业在哪个具体方面 ...

  2. Pandas核心用法

    目录 Numpy和Pandas Numpy科学计算 Pandas数据分析 安装jupyter notebook Numpy语法 创建和基本使用 切片索引 布尔索引 对位运算 矩阵的乘除 其他方法 Pa ...

  3. 链地址法查找成功与不成功的平均查找长度ASL

    晚上,好像是深夜了,突然写到这类题时遇到的疑惑,恰恰这个真题只让计算成功的ASL,但我想学一下不成功的计算,只能自己来解决了,翻了李春葆和严蔚敏的教材没有找到相关链地址法的计算,于是大致翻到两篇不错的 ...

  4. 基础篇:JAVA集合,面试专用

    没啥好说的,在座的各位都是靓仔 List 数组 Vector 向量 Stack 栈 Map 映射字典 Set 集合 Queue 队列 Deque 双向队列 关注公众号,一起交流,微信搜一搜: 潜行前行 ...

  5. 检查redis是否正常运行

    [XX@XXX]$ ps -ef | grep redisXX   8047 1 0 10:06 ? 00:00:03 redis-server *:6379XX   9983 9802 0 11:2 ...

  6. 记一次线上环境 ES 主分片为分配故障

    故障前提 ElasticSearch 版本:5.2 集群节点数:5 索引主分片数:5 索引分片副本数:1 线上环境ES存储的数据量很大,当天由于存储故障,导致一时间 5个节点的 ES 集群,同时有两个 ...

  7. 【Python+postman接口自动化测试】(5)抓包工具Fiddler简介

    Fiddler简介 Fiddler 4.6 下载 http://www.downza.cn/soft/234727.html 为什么使用Fiddler? 可以抓到请求数据,查看Raw格式/表单格式/J ...

  8. OpenHarmony LiteOS C-SKY指令集移植指北

    摘要:本文介绍在OpenHarmony社区LiteOS-M项目中新增C-SKY指令集的开发流程,以及适配相应qemu工程的方法和步骤,供LiteOS内核相关开发者学习交流. 本文分享自华为云社区< ...

  9. PTA 7-2 邻接表创建无向图 (20分)

    PTA 7-2 邻接表创建无向图 (20分) 采用邻接表创建无向图G ,依次输出各顶点的度. 输入格式: 输入第一行中给出2个整数i(0<i≤10),j(j≥0),分别为图G的顶点数和边数. 输 ...

  10. 暑假算法练习Day5

    咕咕了好几天哈哈哈哈,因为这几天在忙一些其他事(bushi ,好吧其实就是自己太懒啦,从今天开始继续每天的算法练习 1010 一元多项式求导 (25 分) 设计函数求一元多项式的导数.(注:\(x^n ...