SQL语句优化记录

维护的系统中有一个统计功能特别慢,需要计算十几分钟,今天分析后发现有一个sql语句执行了近4秒,特意针对SQL进行了优化,记下优化记录。

主要分为两步:

1.优化sql语句

2.建索引

大的sql语句就不贴了,找出其中最慢的一段

select 
	a1.pid,a1.kfqnum ,a1.kfqdj,qsj,jsj,case when (jsj-qsj)/qsj > 1 then 100 ELSE (jsj-qsj)/qsj*100 end as jzssj 
from
(
	select aa.* from zd_kfq aa,(select * from zd_kfq where Kfqnum = 21) bb WHERE aa.Kfqdj = bb.kfqdj and aa.hg=bb.hg
) zz LEFT JOIN
(
	select a.pid pid, kfqnum ,kfqdj,a.sz qsj
	from evaluation_index a
	where 1=1
	and a.pid in(
		select growth_id from evaluation_sub WHERE pid = 'ae80c82c-4172-46f4-895f-29e1e9e7fd3c'
	)
	and a.nian=2018-1
	and a.kfqdj=1
) a1 on zz.Kfqnum = a1.kfqnum LEFT JOIN (
	select a.pid pid, kfqnum ,kfqdj,a.sz jsj
	from evaluation_index a
	where 1=1
	and a.pid in(
		select growth_id from evaluation_sub WHERE pid = 'ae80c82c-4172-46f4-895f-29e1e9e7fd3c'
	)
	and a.nian=2018
	and a.kfqdj=1
) b1 on a1.pid=b1.pid and a1.kfqnum=b1.kfqnum and a1.kfqdj = b1.kfqdj

查询结果如下图,可以看到查询时间是3.5秒左右:

通过explain命令查看一下执行过程:

首先去掉语句嵌套,并且将left join替换为join

select this.pid,kfq.kfqnum,kfq.kfqdj,this.sz jsj,last.sz qsj ,case when (this.sz-last.sz)/last.sz > 1 then 100 ELSE (this.sz-last.sz)/last.sz*100 end as jzssj
from zd_kfq target 
join zd_kfq kfq ON kfq.Kfqdj = target.kfqdj and kfq.hg=target.hg 
join evaluation_index this ON kfq.kfqnum = this.kfqnum  -- and kfq.kfqdj = this.kfqdj
join evaluation_sub sub ON this.pid = sub.growth_id
join evaluation_index last on last.pid = sub.growth_id and this.pid=last.pid and kfq.kfqnum=last.kfqnum -- and kfq.kfqdj = last.kfqdj
where target.kfqnum = 21
AND this.nian = 2018 AND this.kfqdj = target.kfqdj
AND last.nian = 2018-1 AND last.kfqdj = target.kfqdj
AND sub.pid = 'ae80c82c-4172-46f4-895f-29e1e9e7fd3c'

执行时间缩短为0.36秒左右,快了10倍 ,结果少了几条值为null的

再通过explain命令查看一下执行过程:

 针对上面表中this/last,也就是evaluation_index表创建索引,这个在查询中扫描了36321行
 

CREATE INDEX stat_kfq ON evaluation_index (pid,nian,kfqnum,kfqdj) USING BTREE;

执行时间缩短为0.05秒左右

 查看执行过程

可以看到现在除了kfq和sub两个表都已经使用了索引,这两个表数据量比较少,加上索引基本没什么影响

总结

1.先优化sql语句

在保证结果正确的前提下减少使用left join和嵌套查询,能够减少sql执行步骤数量

2.创建索引

针对数据量比较大的表建立联合索引,建立索引遵循最左前缀匹配原则

(1)比如针对一个表A、B、C三个字段建立联合索引,当查询条件为A、AB、ABC、AC都可以使用到索引

(2)如果这个表字段包含除了ABC之外的其他字段D,并且D上面没有被其他索引覆盖,那么查询条件为B、或者C的时候就不会使用索引,explain语句的时候type=all

(3)如果这个表字段只有ABC三个字段,或者还包含是主键的D,则查询条件为B或者C时,也会使用到索引,explain语句的时候type=index

不同type的性能: null > system/const > eq_ref > ref > ref_or_null  >index_merge >  range > index >  all

 

参考:

https://www.cnblogs.com/wangfengming/articles/8275448.html

https://www.jb51.net/article/142840.htm

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值