一次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 Lite 4.8制作“Windows 12 Lite”正式发布

    值得注意的是,这款Windows 12 Lite的宣传标语将矛头直指Windows 10,声称不会迫使用户更新.不会存在病毒或恶意软件.启动速度比Win 10快3倍.提供8万多款优质软件.允许与Win ...

  2. 利用mnist数据集进行深度神经网络

    初始神经网络 这里要解决的问题是,将手写数字的灰度图像(28 像素 x28 像素)划分到 10 个类别中(0~9).我们将使用 MINST 数据集,它是机器学习领域的一个经典数据集,其历史几乎和这个领 ...

  3. 【转】sublime text 2中Emmet插件8个常用的技巧

    因为开始做web项目,所以最近在用sublime编辑器,知道了一个传说中的emmet,原名是zen coding.html神插件可以说是.文章部分内容转自http://www.cnblogs.com/ ...

  4. Block详解二(底层分析)

    Block专辑: Block讲解一 MRC-block与ARC-block Block详解一(底层分析) 今天讲述Block的最后一篇,后两篇仅仅是加深1,2篇的理解,废话少说,开始讲解! __blo ...

  5. MySQL笔记(8)-- 索引类型

    一.背景 前面我们讲了SQL分析和索引优化都涉及到了索引,那么什么是索引,它的模型有什么,实现的机制是什么,今天我们来好好讨论下. 二.索引的介绍 索引就相当书的目录,比如一本500页的书,如果你想快 ...

  6. Mysql性能优化:为什么要用覆盖索引?

    导读 相信读者看过很多MYSQL索引优化的文章,其中有很多优化的方法,比如最佳左前缀,覆盖索引等方法,但是你真正理解为什么要使用最佳左前缀,为什么使用覆盖索引会提升查询的效率吗? 本篇文章将从MYSQ ...

  7. [模拟] Codeforces - 1191C - Tokitsukaze and Discard Items

    Tokitsukaze and Discard Items time limit per test 1 second memory limit per test 256 megabytes input ...

  8. ssm整合配置文件

    web.xml: <!-- 指定spring的配置文件的路径和名称 --> <context-param> <param-name>contextConfigLoc ...

  9. 支持向量机(Support Vector Machine)

    本博客是针对Andrew NG在Coursera上发布的Machine Learning课程SVM部分的学习笔记. 目录 前言 最优化目标(Optimization Objective) 最大化边界的 ...

  10. .NET Core技术研究-配置读取

    升级ASP.NET Core后,配置的读取是第一个要明确的技术.原先的App.Config.Web.Config.自定义Config在ASP.NET Core中如何正常使用.有必要好好总结整理一下,相 ...