MySQL-数据库多表关联查询太慢,如何进行SQL语句优化
工作中我们经常用到多个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语句优化的更多相关文章
- 项目总结04:SQL批量导入数据:将具有多表关联的Excel数据,通过sql语句脚本的形式,导入到数据库
将具有多表关联的Excel数据,通过sql语句脚本的形式,导入到数据库 写在前面:本文用的语言是java:数据库是MySql: 需求:在实际项目中,经常会被客户要求,做批量导入数据:一般的简单的单表数 ...
- Python操作Mysql数据库——多表组合查询
前面我们介绍了单张表的查询,包括模糊查询.分组.排序.各种筛选条件等等操作,在实际应用中,查询的数据往往不止局限在一张表里,通常需要多张表在一起进行组合查询,今天我们将会对Mysql当中的多张有关联的 ...
- ORACLE数据库多表关联查询效率问题解决方案
最近在做项目中遇到多表关联查询排序的效率问题(5张以上40W+数据的表),查询一次大概要20多秒,经过一番苦思冥想,处理方案如下: 1.软件设计初期,需要一对一关联的表应该设计在一张大表里,这样虽然字 ...
- mysql三张表关联查询
三张表,需要得到的数据是标红色部分的.sql如下: select a.uid,a.uname,a.upsw,a.urealname,a.utel,a.uremark, b.rid,b.rname,b. ...
- MySql数据库转设计文档(mysql-font工具和sql语句导出)
一.工具导出 1.使用的是MySQL-Front工具,这个工具使用非常方便,尤其是导出数据的时候,几百万的数据一两分钟就导完了,推荐使用. MySQL-Front下载(只有3.93M):http:// ...
- mysql数据库技术1——基本的增删查改的sql语句
1.数据库语言的分类 DDL:数据库定义语言 data Definition language 用于创建.修改.和删除数据库内的数据结构,如: 1:创建和删除数据库(CREATE DATABASE | ...
- MySQL在大数据、高并发场景下的SQL语句优化和"最佳实践"
本文主要针对中小型应用或网站,重点探讨日常程序开发中SQL语句的优化问题,所谓“大数据”.“高并发”仅针对中小型应用而言,专业的数据库运维大神请无视.以下实践为个人在实际开发工作中,针对相对“大数据” ...
- MySQL数据库--创建表,查询
MySQL创建表: 表(一)Student (学生表): CREATE TABLE `Student` ( `sno` ) DEFAULT NULL, `sname` ) DEFAULT NULL, ...
- 关于MySql数据库设计表与查询耗时分析
本地建一张表persons,使用脚本插入了1000万条数据 下面比较几种查询方法的耗时(查询9000000到9000005这中间5条数据) 查询结果: 1: SELECT * FROM test.pe ...
随机推荐
- OO第四单元作业总结及课程总结
一.本单元作业架构设计 1.第一次作业 本单元首次接触到UML以及相关概念,在面对第一次作业时首先花了很大功夫去阅读官方接口中各种UmlElement的代码,才理解了输入的模型元素中各属性的含义.总的 ...
- Asp.net Core使用EFCore+Linq进行操作
注:EFCore和EF有区别,在core中写的也有一点区别,每个人写法不同仅供参考写的比较细致耐性一点看完会有收获的 首先加上必要的引用 using Microsoft.EntityFramework ...
- spring cloud zuul的回退
当我们使用 @EnableZuulProxy 注解来开启zuul的路由时,默认在@EnableZuulProxy注解上就包含了@EnableCircuitBreaker注解,即开启了断路器功能.那么在 ...
- Noip模拟61 2021.9.25
T1 交通 考场上想了一个$NPC$.应该吧,是要求出图里面的所有可行的不重复欧拉路 无数种做法都无法解出,时间也都耗在这个上面的,于是就考的挺惨的 以后要是觉得当前思路不可做,就试着换一换思路,千万 ...
- 使用google zxing生成二维码图片
生成二维码工具类: 1 import java.awt.geom.AffineTransform; 2 import java.awt.image.AffineTransformOp; 3 impor ...
- $.ajax、$.get和$.post方法成功,完成请求,错误或失败的回调
一.$.get和$.post的不同 1.get通过url提交的,post是通过http消息实体提交的 2.get提交大小限制为2kb,post不限制 3.get提交会被缓存下来,有安 ...
- Java项目中集成钉钉机器人推送消息提醒
前言: 项目中有一个需求,当有新订单产生的时候,希望能够及时通知到业务相关人员进行处理,整体考虑了一下,选用了钉钉机器人提醒功能(公司内部主要也是使用钉钉进行通讯). 操作: 主要分为两部分进行处理: ...
- css 马赛克悬停效果
css 马赛克悬停效果 <!DOCTYPE html> <html lang="en"> <head> <meta charset=
- Part 19 AngularJS Services
What is a service in AngularJSBefore we talk about what a service is in Angular. Let's talk about a ...
- 跟着老猫来搞GO-容器(1)
前期回顾 前面的一章主要和大家分享了GO语言的函数的定义,以及GO语言中的指针的简单用法,那么本章,老猫就和大家一起来学习一下GO语言中的容器. 数组 数组的定义 说到容器,大家有编程经验的肯定第一个 ...