题记
接到任务客户要开发一张报表才能搞验收,时间紧任务重。 了解了需求后开始马不停蹄的开始编写查询的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走索引