记录我的一次基于dataworks大数据平台的关于多栏位SUM求和的ODPS SQL优化

记录我的一次基于dataworks大数据平台的关于多栏位SUM求和的ODPS SQL优化

背景

在我所需要做的需求中,有这样一个场景,简化描述即是,基于阿里云dataworks平台ODPS SQL脚本统计出商品订单表(order_info)的每种商品在每个月的销量情况。
订单表主要字段(订单编号、商品编号、销售月份,每笔订单销售多少件)如下,每个分区订单表数据为2.5亿条
ORDER_INFO

需要统计呈现的report效果如下:
商品每月出件表

问题描述

前提:这个需求本身比这样的描述要复杂的多,需要进行多重f(x)计算,因与此次优化关系不大,遂省去,且仅基于其中一个分区进行操作,简化抽离以方便阅读,但是以下时间结果皆是基于需求本身得到的,而非简化后执行得到的。

一开始,我觉得这样的需求很简单,直接按商品进行group by分组,再用case判断是哪个月份,最后对满足条件的数据进行sum求和不就好啦?所以根据这样的思路,我写下了以下sql

SELECT  goods_id
        ,SUM(CASE WHEN sale_month=7 THEN num END ) AS month7
        ,SUM(CASE WHEN sale_month=8 THEN num END ) AS month8
        ,SUM(CASE WHEN sale_month=9 THEN num END ) AS month9
FROM    order_info
GROUP BY goods_id where goods_id='A'
;

为了便于验证,我在筛选条件上加上了商品条件为A的条件限制(where goods_id=‘A’),针对我原本的需求,这样的sql code 执行了约3分钟左右,对此结果,我认为是正常。于是我放开了goods_id='A’的条件限制,让其直接执行所有数据

SELECT  goods_id
        ,SUM(CASE WHEN sale_month=7 THEN num END ) AS month7
        ,SUM(CASE WHEN sale_month=8 THEN num END ) AS month8
        ,SUM(CASE WHEN sale_month=9 THEN num END ) AS month9
FROM    order_info
GROUP BY goods_id
;

于是,悲剧的事情发生了,竟然跑了2个小时都没有跑完,这不科学!
这里我解释一下,在原有需求里,由于我有***数十甚至上百个***SUM求和函数,还有其他函数,加上数据本身也是多表关联而来,并且数据量有上亿之多,所以执行的非常慢,logview显示经过2个小时才执行了60%。经过logview和explain分析,最终发现执行较慢的原因就在sum求和上。

解决方案

由于SUM函数较多,而SUM函数的求和模式又有规律可循,所以,最终解决方案定为,将【每月卖出件数】作为一个栏位字段来进行统一求和,再将这一列数据转化为行。

思路如下:
第一步,统计出每个商品每个月一共销售多少件,作为临时表1
temp1

第二步,在临时表1的基础上,将销售月份字段转成行形式,存为临时表2,即
temp2
第三步,在临时表2的基础上进行按goods id分组统计,对每月销量进行求和(此处根据我的业务场景,我使用的是求和函数,但不限于求和,可根据自身的业务场景,使用判空或者取MAX都可),最终即得到了我们想要的report
商品每月出件表

实行如下:
有了这样的思路,我们就赶紧实行起来吧~话不多说,优化后的sql如下

SELECT  goods_id
        ,SUM(month7) AS month7 ---此处不限于sum函数
        ,SUM(month8) AS month8 ---此处不限于sum函数
        ,SUM(month9) AS month9 ---此处不限于sum函数
FROM    (
            SELECT  goods_id
                    ,(CASE WHEN sale_month=7 THEN MONTH_NUM END) AS month7
                    ,(CASE WHEN sale_month=8 THEN MONTH_NUM END) AS month8
                    ,(CASE WHEN sale_month=9 THEN MONTH_NUM END) AS month9
            FROM    (
                        SELECT  goods_id
                                ,sale_month
                                ,SUM(num) AS MONTH_NUM
                        FROM    order_info
                        GROUP BY goods_id
                                 ,sale_month
                    ) temp1
        ) temp2
GROUP BY goods_id
;

经过这样的优化后,原需求sql执行时间缩短为30分钟。

小结

A 代码并不是越短越好,以代码精简程度评判优劣的形式不可取;
B 如在大数据开发中遇到类似需要多栏位求和十分耗时,而求和栏位又有共性的问题,不妨尝试将多栏位先转化成列,再转化为行,即用 行列转化 的思想解决来这样的问题。
C 如有不足指出请指出,如有更好的解决办法欢迎补充,谢谢~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值