APP下载
报价宝  ›  科技  › 

问题sql优化:从超过300s优化到1s案例分析

报价宝 来源:baojiabao.com 发布时间:2019-11-16 20:52:00 11月12日更新
报价宝综合消息问题sql优化:从超过300s优化到1s案例分析

概述

今天发现有个专案应用每次一启动后使用就会导致另外一个应用服务直接崩溃,而这两个应用使用的是同个数据库,经过排查可以发现是报表应用的某个查询功能导致,而咨询开发但却查不出是哪条sql,那就只能靠自己排查了..下面是解决的大致过程。

1、开启慢查询

修改my.ini配置,增加引数

slow-query-log=1

slow_query_log_file="epms-slow.log"

long_query_time=10

修改后重启,观察epms-slow.log日志内容。

2、定位慢sql

重新点选报表模组,选择日期后点击查询,等系统崩溃后,观察日志涉及的慢查询sql

发现问题sql如下:

select id, parent, project, name

from zentao.zt_task

where parent = 0

/*and exists (select t.parent from zentao.zt_task t where t.parent > 0)*/

and id in (

select t.parent from zentao.zt_task t where t.parent > 0

);

3、检视执行计划

explain select id, parent, project, name

from zentao.zt_task

where parent = 0

/*and exists (select t.parent from zentao.zt_task t where t.parent > 0)*/

and id in (

select t.parent from zentao.zt_task t where t.parent > 0

);

这里可以看到因为走的全扫,每次都扫5万条,产生笛卡尔积,5万*5万就导致数据库崩溃了。

4、考虑用exists改写sql

explain select id, parent, project, name

from zentao.zt_task t

where parent = 0 and exists (

select a.parent from zentao.zt_task a where a.parent = t.id

)

这里改写后问题还是没解决。

5、考虑with改写

后来发现zt_task表查询了两次,所以考虑with改写来简化,只查一次

WITH tmp AS ( SELECT * FROM zt_task ) SELECT

*

FROM

tmp t1

JOIN tmp t2 ON t1.id = t2.parent

好吧,mysql5.7还不支援with改写,只有到mysql 8版本才支援,所以这里只能放弃这种办法了

6、用子查询join改写

SELECT

distinct t1.parent,

t1.id,

t1.project,

t1.NAME

FROM

zentao.zt_task t1

JOIN ( SELECT t.parent FROM zentao.zt_task t WHERE t.parent > 0 ) ta ON t1.id = ta.parent

AND t1.parent =0

这里要记得去重,改写后查询在1秒内得出结果,满足需求。

总结

通过这道案例一定要记住,多表查询的效能是很差的,当然,效能差是有一个前提的:资料量大。子查询 = 简单查询 + 限定查询 + 多表查询 + 统计查询的综合体;

在之前强调过多表查询不建议大家使用,因为效能很差,但是多表查询最有利的替代者就是子查询,所以子查询(子查询指的就是在一个查询之中嵌套了其他的若干查询)在实际的工作之中使用的相当的多。

后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注一下~

文章标签: 报价宝 降噪耳机价格 耳机价格 红米手机价格 华为手机价格 小米手机价格 电视机价格 笔记本电脑价格 笔记本价格 汽车价格 手机价格 笔记本价格 小米手机价格 华为手机价格 红米手机价格