记录我的一次基于dataworks大数据平台的关于多栏位SUM求和的ODPS SQL优化
记录我的一次基于dataworks大数据平台的关于多栏位SUM求和的ODPS SQL优化
背景
在我所需要做的需求中,有这样一个场景,简化描述即是,基于阿里云dataworks平台用ODPS SQL脚本统计出商品订单表(order_info)的每种商品在每个月的销量情况。
订单表主要字段(订单编号、商品编号、销售月份,每笔订单销售多少件)如下,每个分区订单表数据为2.5亿条:
需要统计呈现的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
第二步,在临时表1的基础上,将销售月份字段转成行形式,存为临时表2,即
第三步,在临时表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 如有不足指出请指出,如有更好的解决办法欢迎补充,谢谢~
- SQL语句中关于空记录sum求和返回null值的处理,兼谈case的处理
- 用SqlDataReader读数据后判断[字段或记录]是否为空
- 一周工作总结--一次SQL优化记录
- SUM 是SQL语句中的标准求和函数,如果没有符合条件的记录,那么SUM函数会返回NULL。但咱们想返回的是0而不是Null
- 实战记录:一次真实的线上SQL语句优化
- 一周工作总结--一次SQL优化记录
- SQL Server 数据库中SQL优化的一次记录
- SQL on Hadoop在快手大数据平台的实践与优化 - SQL优化
- 大数据下Sql优化心得记录
- 关于同一条记录在两个日期之间填补数据的sql
- sql语句优化一次进行多条记录的-----插入和修改
- Java Develop——基于 MySQL 的 SQL 规约/优化记录
- 数据库操作_连接SQL Server数据库示例;连接ACCESS数据库;连接到 Oracle 数据库示例;SqlCommand 执行SQL命令示例;SqlDataReader 读取数据示例;使用DataAdapter填充数据到DataSet;使用DataTable存储数据库表;将数据库数据填充到 XML 文件;10 使用带输入参数的存储过程;11 使用带输入、输出参数的存储过程示;12 获得数据库中表的数目和名称;13 保存图片到SQL Server数据库示例;14 获得插入记录标识号;Exce
- 基于ArcEngine+C#实现的JLKDataManager空间数据平台架构设计
- 关于sql优化二:数据分区技术
- 一次sql优化的记录
- 组函数(avg(),sum(),max(),min(),count())、多行函数,分组数据(group by,求各部门的平均工资),分组过滤(having和where),sql优化 .
- 关于mysql中删除重复记录,并保留重复数据中的一条数据的SQL语句理解
- 记录一次帮策划写的基于VBA的数据转化工具
- 自己动手写个ORM实现(4) 关于反射DataRow数据记录到实体性能的优化