一次mysql多表查询(left jion)优化案例

在新上线的供需模块中,发现某一个查询按钮点击后,出不来结果,找到该按钮对应sql手动执行,发现需要20-30秒才能出结果,所以服务端程序判断超时,故先不显示结果

以下是对这条查询的优化记录

1 数据库配置

数据库配置:4C8G

主表数据:3W+

2 sql语句

提取sql语句,简化如下

SELECT
taba.id,
taba.title,
taba.type,
taba.end_time,
tabb.username,
tabc.orgname
FROM
taba
LEFT JOIN tabd ON tabd.info_id = taba.id
LEFT JOIN tabe ON tabe.sdo_id = taba.id
LEFT JOIN tabb ON tabb.id = taba.creator
LEFT JOIN tabc ON tabc.id = taba.organization_id
WHERE
taba.`STATUS` = 'PUBLISH'
AND tabd.type = 'INDEX'
AND tabd.`VALUE` = '1'
AND taba.info_type = 'SUPPLY'
GROUP BY
taba.id
ORDER BY
taba.create_time DESC
LIMIT 100

3 优化记录

3.1 数据库索引

首先第一反应,查sql是否走了索引

EXPLAIN
select ......

从索引检查结果发现

  1. tabe只有主键索引,没有sdo_id的索引

    经过确定sdo_id是通过uuid制作,重复数很少,可以增加上索引
  2. 其他条件虽然也没走索引,但是属于枚举值,重复性高,没有加索引的条件

经过添加索引,数据查询时间降低到3秒以内,所以正确的索引才是王道

3.2 返回数据限制

经过与开发人员沟通,确定可以每次只取10条数据,所以要求他们更改limit语句限制为limit 10

经过修改limit语句,数据库直插时间已经变味1.7秒

3.3 spring框架错误的conut *

经过前两部优化,按理2秒左右app就能显示数据,但是时间上却需要4秒钟

通过sql慢查询日志,发现在这条sql执行前,spring框架自动执行了一个select count(0) from (......)的操作来做分页,但是所以导致查询时间是理论上的2倍

再次与开发确定,不用框架的自动分页功能,改为代码层手动分页

结果修改框架的分页,app查询时间达到2秒内,已基本得到解决

3.4 极限优化limit

查询优化到2秒,已基本可以接受,但是先到数据才3万多行,感觉还是不能接受,继续找原因,发现如下:

  • 3万+数据,但是sql执行结果却显示扫描了100多万行数据

观察sql语句,可以发现是先做了多次left join后,对结果取limit,那能不能先取limit 10再进行查询呢,于是把sql优化如下

SELECT
taba.id,
taba.title,
taba.type,
taba.end_time,
tabb.username,
tabc.orgname
FROM
taba
LEFT JOIN tabd ON tabd.info_id = taba.id
LEFT JOIN tabe ON tabe.sdo_id = taba.id
LEFT JOIN tabb ON tabb.id = taba.creator
LEFT JOIN tabc ON tabc.id = taba.organization_id
WHERE
tabd.type = 'INDEX'
AND tabd.`VALUE` = '1'
AND taba.id IN (
SELECT * FROM
( SELECT id FROM taba WHERE `STATUS` = 'PUBLISH'
AND info_type = 'SUPPLY'
ORDER BY taba.create_time DESC LIMIT 10 ) AS tmp
)

优化方法:

  • 将limit语句通过子查询放入where条件中
  • sql将先执行子查询获取10条id数据
  • 让后将10条id拿去前面做join

优化结果

  • sql执行时间达到0.117秒,再一次质的飞跃
  • 基本做到秒加载,点击按钮,一秒内出结果

3.4.1

第二天一觉醒来,觉得这个sql还有值得优化的地方,于是分别提取出各语句执行后,发现耗时最长的是limit条件,耗时0.09s

优化方法

  • 查找发现原因是order by条件create_time列未加索引,导致做了一次全表扫描
  • 于是增加上create_time索引

优化结果

  • sql执行时间变为0.068s
  • 再次说明正确的索引才是王道

3.5 优化后记

其实sql中还有几个可以优化的地方,比如:

  • 4个left join中的3个可以改成inner join
  • 原语句的group by,经测试改掉可优化0.3秒(1.7秒处)
  • limit语句可以放到from处先处理等

但是:

  • sql优化是长期的过程
  • 优先解决影响业务的慢查询
  • 优先解决占时间比例大的慢查询
  • 咱是运维,不是DBA,还有高可用等着我玩
  • 因此已经达到要求,甚至超额完成,就不用再管芝麻了

记一次mysql多表查询(left jion)优化案例的更多相关文章

  1. MySQL 回表查询 & 索引覆盖优化

    回表查询 先通过普通索引的值定位聚簇索引值,再通过聚簇索引的值定位行记录数据 建表示例 mysql> create table user( -> id int(10) auto_incre ...

  2. MySQL多表查询之外键、表连接、子查询、索引

    MySQL多表查询之外键.表连接.子查询.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为 ...

  3. Mysql 单表查询 子查询 关联查询

    数据准备: ## 学院表create table department( d_id int primary key auto_increment, d_name varchar(20) not nul ...

  4. (转)Mysql 多表查询详解

    MySQL 多表查询详解 一.前言  二.示例 三.注意事项 一.前言  上篇讲到mysql中关键字执行的顺序,只涉及了一张表:实际应用大部分情况下,查询语句都会涉及到多张表格 : 1.1 多表连接有 ...

  5. MySQL多表查询回顾

    ----------------------siwuxie095 MySQL 多表查询回顾 以客户和联系人为例(一对多) 1.内连接 /*内连接写法一*/ select * from t_custom ...

  6. python 3 mysql 单表查询

    python 3 mysql 单表查询 1.准备表 company.employee 员工id id int 姓名 emp_name varchar 性别 sex enum 年龄 age int 入职 ...

  7. python3 mysql 多表查询

    python3 mysql 多表查询 一.准备表 创建二张表: company.employee company.department #建表 create table department( id ...

  8. Mysql 单表查询-排序-分页-group by初识

    Mysql 单表查询-排序-分页-group by初识 对于select 来说, 分组聚合(((group by; aggregation), 排序 (order by** ), 分页查询 (limi ...

  9. Mysql 单表查询where初识

    Mysql 单表查询where初识 准备数据 -- 创建测试库 -- drop database if exists student_db; create database student_db ch ...

随机推荐

  1. 波兰政府在继韩国之后也增加了对 Linux 的使用

    导读 前段时间, 韩国政府起草了一项战略,准备采用基于 Linux 的开源操作系统全面取代 Windows 7,以摆脱对其的依赖. 目前,波兰的社会保险公司 ZUS( Zakład Ubezpiecz ...

  2. 基于linux下的NIST数字测试包安装过程

    基于linux下的NIST数字测试包安装过程 1. 首先解决windows文件不能粘贴到Ubuntu的问题 选择利用VMware Tools进行解决 打开虚拟机VMware Workstation,启 ...

  3. javascript 自动选中容器里的文字

    前些时间有这么个需求,需要实现选中div里面的文字,选中了的文字可直接按ctrl+v(或者右键)实现黏贴操作. html代码: <div id="text" class=&q ...

  4. Requests发Post请求data里面嵌套字典

    一.Post请求,data里面嵌套字典 Requests发Post请求,data里面嵌套字典的常见形式如下: info = { "appid": "123", ...

  5. 面试话痨(二)C:JAVA String,别以为你穿个马甲我就不认识你了

    面试话痨系列是从技术广度的角度去回答面试官提的问题,适合萌新观看!   面试官,别再问我火箭怎么造了,我知道螺丝的四种拧法,你想听吗? String相关的题目,是面试中经常考察的点,当面试中遇到了St ...

  6. 1. postman使用

    postman使用教程: https://blog.csdn.net/fxbin123/article/details/80428216 http://bayescafe.com/tools/use- ...

  7. .NET的资源并不限于.resx文件

    为了构建一个轻量级的资源管理框架以满足简单的本地化(Localization)的需求,我试图直接对现有的Resource编程模型进行扩展.虽然最终没能满足我们的需求,但是这两天也算对.NET如何进行资 ...

  8. Windows软件包管理工具 - Chocolatey

    概述 windows下的软件安装管理器(用于自动管理软件安装,更新,卸载) Chocolatey引入了真正的包管理概念,使您能够对事物进行版本控制,管理依赖关系和安装顺序,更好的库存管理以及其他功能 ...

  9. 基于 websocket 的多端桥接平台

    我们现在的业务是基于新闻客户端实现的,都要经过新闻客户端的环境,进行前后端数据上的交互.但是我们在调试过程中,非常的不方便. 通常使用的工具有:modheader, postman, fiddler ...

  10. 直方图均衡算法(Histogram Equalized)

    Lab1: Histogram Equalization 1. 实验环境(C++) 操作系统版本 MacOS Catalina 10.15 OpenCV4.0 (imgcodecs | core | ...