记一次一头雾水的sql调优(多字段表)

  入职新公司,接手一个旧功能,发现一个接口请求需要8s左右,定位到是sql问题,业务为根据AdId查询aCost,bCost,cCost的合值与比例,耗时7s左右,其中aCost,bCost,cCost的数据类型为decimal,原sql如下

 SELECT AdId adId, 
		SUM(aCost) aCost, 
		SUM(bCost) bCost ,
		SUM(cCost) cCost, 
		ROUND(SUM(aCost) / SUM(cCost), 4 ) ac,
		ROUND(SUM(bCost) / SUM(cCost), 4 ) bc
		FROM t_report WHERE AdId IN (
		193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164
	) and cDate>='2010-02-29' and cDate<='2030-03-04' GROUP BY AdId 

t_report这张表的数据量在50w左右,最开始认为可以查询条件进行优化,可以把AdId与cDate创建联合索引,进行优化时间,发现这个索引已经被创建了,所以问题不在这里,最后发现t_report 这张表存在80多个字段,所以想到查询时因为涉及到回表操作,所以在回表时,因为字段过多,所以会很耗时,于是创建AdId,cDate,aCost,bCost,cCost的联合索引,耗时直接到了1s以内,但是我发现t_report这张表因为很多业务在使用,这种创建联合索引的方式并不合适,不可能把每个业务都建立对应索引,是一种治标不治本的做法。于是想到利用临时表的方式先把AdId,aCost,bCost,cCost查询出,然后再进行聚合查询,具体sql如下

 SELECT AdId adId, 
		SUM(aCost) aCost, 
		SUM(bCost) bCost ,
		SUM(cCost) cCost, 
		ROUND(SUM(aCost) / SUM(cCost), 4 ) ac,
		ROUND(SUM(bCost) / SUM(cCost), 4 ) bc from(
        select AdId,aCost,bCost,cCost
		FROM t_report WHERE AdId IN (
		193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164
	) and cDate>='2010-02-29' and cDate<='2030-03-04') tmp GROUP BY tmp.AdId 

这条sql的执行时间在1s左右,在不创建索引的情况下已经达到预期。用explain查看sql的执行计划,发现临时表的查询并没有使用上索引,因为AdId与cDate已经被前人创建过联合索引,觉得非常奇怪,于是使用force index 强制使用索引,sql如下

 SELECT AdId adId, 
		SUM(aCost) aCost, 
		SUM(bCost) bCost ,
		SUM(cCost) cCost, 
		ROUND(SUM(aCost) / SUM(cCost), 4 ) ac,
		ROUND(SUM(bCost) / SUM(cCost), 4 ) bc from(
        select AdId,aCost,bCost,cCost FROM t_report 
        force index (IDX_ADID_CDATE)
        WHERE AdId IN (
		193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164
	) and cDate>='2010-02-29' and cDate<='2030-03-04') tmp GROUP BY tmp.AdId 

但sql的执行时间为3s左右,比全表查询更慢了。这正是一头雾水的地方,可能涉及到MySQL自身对sql的优化,这点查询过很多文档并没有找到答案。

整个sql的优化过程如上,问题主要为t_report字段过多,后续要对该表进行拆分操作。

后记:在正式环境运行之后,发现此次sql优化作用不大,后续发现开发版本MySQL版本5.6,正式环境为5.7,同一条sql执行计划都不相同,强制使用索引效果又不一。

路漫漫其修远兮

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值