优化查询速度 - SQL替换Service
Service 接口问题
下面是原先的 Service 实现类代码,有门店 ID、订单状态、查询时间段,然后查出了所有的结果,继续使用 java8 的特性获取汇总结果,随着项目的推移,数据量越来越大,这种方式是不可取的,随便都能上几十秒查不出来,导致请求超时,下面我们就来优化一下这个方法
SQL 优化
先把上面的方法都转换成 SQL 语句的写法,得到下面的 5 个查询 SQL
select sum(A.pay_money) originPrice, count(A.id) countOrder, sum(A.pay_money) payMoney
from biz_order_info A
where A.`status` = 1 and A.order_status = 2 and A.store_id = 1;
select sum(A.pay_money) smPayMoney
from biz_order_info A
where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 1;
select sum(A.pay_money) rlPayMoney
from biz_order_info A
where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 2;
select sum(A.pay_money) sjPayMoney
from biz_order_info A
where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 3;
select sum(A.pay_money) xjPayMoney
from biz_order_info A
where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 4;
整理一下代码,通过union all连接,最简单的方法,后端使用 List 来接收返回值,有一定的可行性
select * from (
(select sum(A.pay_money) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1)
union all
(select count(A.id) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1)
union all
(select sum(A.pay_money) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1)
union all
(select sum(A.pay_money) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 1)
union all
(select sum(A.pay_money) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 2)
union all
(select sum(A.pay_money) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 3)
union all
(select sum(A.pay_money) 'value' from biz_order_info A where A.`status` = 1 and A.order_status = 2 and A.store_id = 1 and A.pay_way = 4)
) X;
查询结果
当我放到项目中时,发现还有查询条件,时间段,如果上面的 SQL 加上时间段,将会变的非常臃肿且难维护,所以上面的 SQL 报废了,不能使用,继续优化 SQL
-- 最开始的SQL
select A.*
from biz_order_info A
where A.`status` = 1 and A.order_status = 2;
-- 初步汇总,拿到3个我们需要的值
select sum(A.pay_money), count(A.id), sum(A.pay_money)
from biz_order_info A
where A.`status` = 1 and A.order_status = 2;
问题来了,怎么在已经查询出的结果中分支付方式汇总数据?
这里我使用的是 sum + case when 结构,分类汇总数据,再次优化 SQL
select sum(A.pay_money) originPrice, count(A.id) countOrder, sum(A.pay_money) payMoney,
sum(case A.pay_way when '1' THEN A.pay_money ELSE 0 END) smPayMoney,
sum(case A.pay_way when '2' THEN A.pay_money ELSE 0 END) rlPayMoney,
sum(case A.pay_way when '3' THEN A.pay_money ELSE 0 END) sjPayMoney,
sum(case A.pay_way when '4' THEN A.pay_money ELSE 0 END) xjPayMoney
from biz_order_info A
where A.`status` = 1 and A.order_status = 2
查询结果
接下来随便一试,有两种方式处理业务逻辑了
- 方法一:后台使用 Vo 实体类直接接收
- 方法二:使用 Map 接收
下面是测试结果,Service 操作性能提升了 75.61% ,所以以后不要查询所有的数据!!!
优化后的接口
不要一次性查询所有表数据 一次性 SQL 解决的问题,就不要写 Service 方法了