「这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战」
题记
接到任务客户要开发一张报表才能搞验收,时间紧任务重。
了解了需求后开始马不停蹄的开始编写查询的sql了,然后劈里啪啦的敲代码了。
终于搞完了,丢给了现场去测试。
现场反馈数据展示可以了,取数也是对的,然后让客户看一眼。
客户一打开报表只见页面再那里转圈圈,然后客户喝了几口茶,慢慢的说到太太太慢了。
现场这时就反馈了这报表需要优化下。
需求
系统里面有科目表、预算执行表。。。例如预算上报等
科目表从名字就可以看出是存放的预算科目表,执行表放的是付款挂接的预算明细
报表的其他统计的先不说暂且先不关注,主要是执行数据的统计。
执行统计里面如果是上级科目需要汇总子科目的执行数,但执行表的数据都是明细。
撸代码
开始的做法
直接丢个子查询进去
(SELECT SUM(fp.PROCESS_CUR_MONEY)
FROM fbs_budget_process fp
WHERE fp.status = '95'
AND fp.process_date >= pm.begin_date
AND fp.process_date <= pm.END_DATE
AND fp.item_code LIKE CONCAT(pm.itemCode, '%')
) processMoney
优化
经过一步一步拆分执行的sql,发现就是执行金额统计慢. 只用了三个字段分别是status、process_date、item_code 加索引吧(process_date、item_code)。
直接跑了下还是慢
来看下执行计划
一脸懵逼 索引只执行了日期process_date,没有科目item_code
在我得理解中科目关联我用了like abc% 应该走索引的
然后我试下,固定科目的时候索引出来了。难道动态匹配的时候索引会消失,有知道的老铁可以给我留言
中途试了下locate、POSITION (有效的)都没效果
如果是%jkjk 的可以用反转函数求解
没招了,最后发现in操作居然走索引,
修改前
(SELECT SUM(fp.PROCESS_CUR_MONEY)
FROM fbs_budget_process fp
WHERE fp.status = '95'
AND fp.process_date >= pm.begin_date
AND fp.process_date <= pm.END_DATE
AND fp.item_code LIKE CONCAT(pm.itemCode, '%')
)
修改后 试下了这下走索引了
(SELECT SUM(fp.PROCESS_CUR_MONEY)
FROM fbs_budget_process fp
WHERE
fp.item_code in (select fi.ITEM_CODE from fbs_item fi where fi.ITEM_CODE like CONCAT(pm.itemCode,'%') )
AND fp.status = '95'
AND fp.process_date BETWEEN pm.begin_date and pm.END_DATE)
回顾下最后
平时在网上看 like 匹配符在右边的时候是走索引的,但这个好像只能是固定的前缀
其实 like CONCAT(pm.itemCode,'%') 动态匹配的时候是不走索引的
like CONCAT('200','%') 固定了就走索引了
转换:
有单一的 like concat转为in 和 小表的like concat
fp.item_code in (select fi.ITEM_CODE from fbs_item fi where fi.ITEM_CODE like CONCAT(pm.itemCode,'%') )
处理用了科目表(fbs_item)数据量小,
在匹配出子科目的时候执行速度快点,
然后主表in走索引