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

一次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 hsoi.id IN (
	SELECT *FROM
		(
			SELECT id		FROM	taba
			WHERE	`STATUS` = ‘PUBLISH‘
			AND info_type = ‘SUPPLY‘
			ORDER BY taba.create_time DESC
			LIMIT 10
		) AS t
)

优化方法:

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

优化结果

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

3.5 优化后记

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

  • 4个left join中的3个可以改成inner join
  • 原语句的group by,经测试改掉可优化0.3秒(1.7秒处)
  • 几个表之间可以相同的列可以做外键

但是:

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

原文地址:https://www.cnblogs.com/noah-luo/p/12695117.html

时间: 2024-12-22 12:22:35

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

python3 mysql 多表查询

python3 mysql 多表查询 一.准备表 创建二张表: company.employee company.department #建表 create table department( id int, name varchar(20) ); create table employee( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male'

MySQL多表查询回顾

----------------------siwuxie095 MySQL 多表查询回顾 以客户和联系人为例(一对多) 1.内连接 /*内连接写法一*/ select * from t_customer c,t_linkman l where c.cid=l.clid /*内连接写法二(inner 可以省略不写)*/ select * from t_customer c inner join t_linkman l on c.cid=l.clid 2.左外连接 /*左外连接(outer 可以省

mysql多表查询方法(left join(左连接),right join (右连接),inner join (内连接)的区别)

表A记录如下:  aID aNum  1 a20050111  2 a20050112  3 a20050113  4 a20050114  5 a20050115  表B记录如下:  bID bName  1 2006032401  2 2006032402  3 2006032403  4 2006032404  8 2006032408  创建这两个表SQL语句如下:  CREATE TABLE a  aID int( 1 ) AUTO_INCREMENT PRIMARY KEY ,  a

MySQL information_schema表查询导致内存暴涨

case:下面的一条sql语句,导致mysql实例内存暴涨: select * from tables where table_name not in(select table_name from partitions group by table_name having count(*)>1 ); mysql 5.5, 1w+的innodb表. 下面看下调查的结果: 1.  sql的执行情况以及内存分配:   step1: 构造information_schema.tables临时表 1.1 

MYSQL 连表查询及别名用法

MYSQL连表查询是两个表之间的查询或者更多表之间查询,通过外键的方式查询所有的数据,在查询过程中产生字段的重复,为了区分这种情况数据库设计别名,有的表很长,也可以用别名. 1,连表查询 INNER JOIN ,LEFT JOIN,RIGHT JOIN INNER JOIN(内连接,或等值连接):获取两个表中字段匹配关系的记录.LEFT JOIN(左连接):获取左表所有记录,即使右表没有对应匹配的记录.RIGHT JOIN(右连接): 与 LEFT JOIN 相反,用于获取右表所有记录,即使左表

4 - MySQL:多表查询

MySQL:多表查询 一,介绍 本节主题 多表连接查询 复合条件连接查询 子查询 准备工作 #建表 create table department( id int, name varchar(20) ); create table employee( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male', age int, dep_id int

mysql in 子查询 效率慢 优化(转)

现在的CMS系统.博客系统.BBS等都喜欢使用标签tag作交叉链接,因此我也尝鲜用了下.但用了后发现我想查询某个tag的文章列表时速度很慢,达到5秒之久!百思不解(后来终于解决),我的表结构是下面这样的,文章只有690篇. 文章表article(id,title,content)标签表tag(tid,tag_name)标签文章中间表article_tag(id,tag_id,article_id)其中有个标签的tid是135,我帮查询标签tid是135的文章列表用以下语句时发现速度好慢,我文章才

MYSQL 分析表、检查表和优化表

1. 对表进行优化 ( 优化表主要作用是消除删除或者更新造成的空间浪费) 2. 对表进行分析(分析关键字的分布, 分析并存储MyISAM和BDB表中键的分布) 3. 对表进行检查(检查表的错误,并且为MyISAM更新键的统计内容) 4. 对表进行修复(修复被破坏的MyISAM表)   1.分析表   MySQL中使用ANALYZE TABLE语句来分析表,该语句的基本语法如下:   ANALYZE TABLE 表名1 [,表名2…] ; 使用ANALYZE TABLE分析表的过程中,数据库系统会

python开发mysql:单表查询&多表查询

一 单表查询,以下是表内容 1 一 having 过滤 2 1.1 having和where 3 select * from emp where id > 15; 4 解析过程;from > where 找到数据 > 分组(没有默认一个组)> select 打印 where是出结果之前 5 select * from emp having id > 15; 6 解析过程;from > where 找到数据(没有约束条件,就是整个表)) > 分组(没有默认一个组)&