增量ETL (长周期指标) 优化方案
在日常数据处理过程中避免不了要计算跨长周期数据指标统计需求,类似于如下:
1、 统计每个城市(过去30天)用户浏览次数;
统计每个城市(本年)用户浏览次数;
统计每个城市(历史至今)用户浏览次数;
2、统计每个城市(过去30天|本年|历史至今)交易用户数;
3、数据集部分数据行存在状态变化数据指标需求。
通常面对以上数据指标需求,最大的问题是跨长周期数据量往往是巨大的或者数据周期范围不固定。下面依次求解。
场景1:统计(过去30天|本年|历史至今)用户浏览次数?
常规解决方案如下:
|
select city_id as city_id, count(1) as pv from events t1 where p_date >= date_add(current_date(),-31) and p_date <= date_add(current_date(),-1) group by city_id ; |
面临的问题,过去30天埋点事件数据量巨大,服务器无法承受且此简单SQL运行时间太长。
解决思路:
通过构建增量更新的中间表,降低结果SQL扫描数据量,从而优化任务的执行时间和资源消耗问题。
1、 设计中间表
|
create table e_city_day_indi( city_id bigint pv int ) partitioned by(p_date string) stored as parquet ; |
e_city_day_indi有两种加载方法,我分别称其为日增量更新方法和循环迭代更新方法,用于方便后续问题描述。
l 日增量更新:每天汇总当天数据计算出每个城市PV,并且存储到当天日期分区;
优点 更通用;
缺点 不能完全避免多分区扫描,且可能造成小文件过多。
l 循环迭代更新:每天新增数据和前一天快照数据做合并,并且将结果存储到当天日期分区。
优点 应用端仅扫描最新分区即可满足需求;
缺点 应用面较窄,部分长周期需求无法满足。
2、 ETL实现
|
日增量更新 |
insert overwrite table e_city_day_indi partition(p_date) select city_id as city_id, count(1) as pv, date_add(current_date(),-1) as p_date from events where p_date = date_add(current_date(),-1) group by city_id ; |
|
循环迭代更新 |
insert overwrite table e_city_day_indi partition(p_date) select city_id, sum(pv) as pv, date_add(current_date(),-1) as p_date from ( select city_id as city_id, count(1) as pv from events where p_date = date_add(current_date(),-1) group by city_id union all select city_id, pv from e_city_day_indi where p_date = date_add(current_date(),-2) ) t group by city_id ; |
3、 优化后取数逻辑
|
日增量更新取数SQL |
select city_id, sum(pv) as pv from e_city_day_indi where p_date >= date_add(current_date(),-31) and p_date <= date_add(current_date(),-1) group by city_id ; |
|
循环迭代更新取数SQL |
select city_id, pv from e_city_day_indi where pdate = date_add(current_date(),-1) ; |
以上两种增量加载方法可以满足问题1需求,同时降低了加工数据量。
场景2:统计每个城市(过去30天|本年|历史至今)交易用户数
常规解决方案如下:
|
select city_id, count(distinct user_id) as uv from events where p_date >= date_add(current_date(),-31) and p_date <= date_add(current_date(),-1) group by city_id ; |
典型count distinct类型需求,面临的问题,过去30天埋点事件数据量巨大,服务器无法承受且此简单SQL运行时间太长。
解决思路:
通过构建增量更新的中间表,降低结果SQL扫描数据量,从而优化任务的执行时间和资源消耗问题。
1、 设计中间表
|
create table e_city_day_indi( city_id bigint, user_id bigint, pv int ) partitioned by(p_date) stored as parquet ; |
e_city_day_indi数据加载方法在这里仅介绍日增量更新方法。
2、ETL实现
|
日增量更新 |
insert overwrite table e_city_day_indi partition(p_date) select city_id, user_id, count(1) as pv, date_add(current_date(),-1) as p_date from events where p_date = date_add(current_date(),-1) group by city_id,user_id ; |
3、优化后取数逻辑
|
日增量更新 |
select city_id, count(distinct user_id) as uv, sum(pv) as pv from e_city_day_indi where p_date >= date_add(current_date(),-31) and p_date <= date_add(current_date(),-1) group by city_id ; |
场景3:数据集部分数据行存在状态变化数据指标需求
这种需求场景比较特殊,是针对全量数据做update操作,一般性问题是全表数据量较大,但是需要update数据量较小,且基于hive解决方案,update是较难以处理的场景。
解决思路:将变化数据和明确不变数据做分离(能否合理做数据热度分离是关键)。具体实施细节是设计分区表,将少量变化数据存储一个分区,将大量不变数据存储在另一个分区,设计历史数据更新的仅扫描活跃分区即可。
实施方案:
l 设计目标表两个分区(或者日期分区下设计二级分区)
活跃分区:用来存储生命周期未结束且可能存在update操作的数据。
非活跃分区:用来存储明确生命周期结束数据。
l 设计日期分区
历史日期分区(p_date <= current_date())存储生命周期结束的数据行;
未来日期分区(p_date = ‘9999-12-31’)存储生命周期尚未结束的数据行。
以上3种典型场景是做数据开发过程中较基础也是比较常见的增量ETL开发场景,使用合适的方法处理问题可以大大减少资源消耗同时可以有效降低执行时间。
增量ETL (长周期指标) 优化方案的更多相关文章
- 数据库SQL优化大总结之 百万级数据库优化方案(转载)
网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...
- mysql 百万级数据库优化方案
https://blog.csdn.net/Kaitiren/article/details/80307828 一.百万级数据库优化方案 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 wher ...
- 前端项目优化 -Web 开发常用优化方案、Vue & React 项目优化
github github-myBlob 从输入URL到页面加载完成的整个过程 首先做 DNS 查询,如果这一步做了智能 DNS 解析的话,会提供访问速度最快的 IP 地址回来 接下来是 TCP 握手 ...
- C++高并发场景下读多写少的优化方案
概述 一谈到高并发的优化方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读 ...
- Redmine性能优化方案
近来公司redmine服务器表现很糟糕,在16核,64GRAM的机器上,压测结果竟然只有每秒5~7个请求,部分页面一个都出不来. 以下是我对Redmine性能优化方案: redmine服务器性能问题排 ...
- 移动 H5 首屏秒开优化方案探讨
转载bang大神文章,原文<移动 H5 首屏秒开优化方案探讨>,此文仅仅用做自学与分享! 随着移动设备性能不断增强,web 页面的性能体验逐渐变得可以接受,又因为 web 开发模式的诸多好 ...
- 五个Taurus垃圾回收compactor优化方案,减少系统资源占用
简介 TaurusDB是一种基于MySQL的计算与存储分离架构的云原生数据库,一个集群中包含多个存储几点,每个存储节点包含多块磁盘,每块磁盘对应一个或者多个slicestore的内存逻辑结构来管理. ...
- 从350ms到80ms,揭秘阿里工程师 iOS 短视频优化方案
内容作为 App 产品新的促活点,受到了越来越多的重视与投入,短视频则是增加用户粘性.增加用户停留时长的一把利器.短视频的内容与体验直接关系到用户是否愿意长时停留,盒马也提出全链路内容视频化的规划,以 ...
- 揭秘盒马鲜生 Android 短视频秒播优化方案
短视频作为内容重要的承载方式,是吸引用户的重点,短视频的内容与体验直接关系到用户是否愿意长时停留.因此,体验的优化就显得尤为重要.上一篇我们分享了 iOS 短视频秒播优化,这篇我们来聊聊 Androi ...
随机推荐
- Oracle数据导出导入(PL/SQL工具)
做了那么多年的开发第一次写博客,一开始是没想过要写博客的,后来想写,却一直不敢写,一个是怕自己写的不好,误导人家,二来是不太自信.现在想起写博客是因为,真正的勇士敢于面临淋漓的鲜血,希望能提高自己,也 ...
- Python之数据分析
什么是数据分析? 运用不同行业中,专门从事行业数据搜集.整理.分析,并依据数据做出行业研究.评估和预测的专业人员. 熟悉行业知识.公司业务及流程,最好有自己独到的见解,若脱离行业认知和公司业务背景,分 ...
- zabbix--自定义监控项vsftpd
Zabbix 自定义监控项之监控 vsftpd zabbix 提供了很多监控选择,功能丰富,我们还可以根据自定义来监控想要监控一些日常的服务等. 说明: 此处我们通过监控 ftp (自定义命令),实现 ...
- Shell 日常 ip 端口可用性测试
ip port 可用测试 telnet 测试某个ip 端口是否可用很方便,但是如果ip比较多,写脚本就不方便了因为是阻塞的 这里强烈推荐 nc nc -z -w 1 127.0.0.1 8990 这里 ...
- 《快活帮》第八次团队作业:Alpha冲刺
项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8-软件测试与ALPHA冲刺 团队名称 快活帮 作业学习目标 (1)掌握 ...
- jQuery扩展$.fn、$.extend jQery命名方法扩展 练习总结
<script> $.fn.hello = function(){ //扩展jQuery实例的自定义方法,基于$.fn的jq方法扩展 this.click(function(){ ...
- P1657选书-(dfs)
https://www.luogu.org/problemnew/show/P1657 解题:对于某个人喜欢的两本书,选或者是不选! 坑:数据有一组是0的,按dfs会出错,0本书选个屁,有啥意义?不给 ...
- re.sub 实现多处替换
1 | 表示或的意思 将所有字母替换掉 result_content = re.sub('a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z', ...
- cc2530中单片机的通用I/O接口
cc2530中有21个输入/输出引脚. 这些引脚可以设置为通用I/O或者设置为外设I/O.(其实这里的外设还是不太懂到底指什么,网上说输入设备,但是通用I/O也可以输入啊,为什么要弄外设I/O?) 其 ...
- bzoj4066: 简单题 K-Dtree
bzoj4066: 简单题 链接 bzoj 思路 强制在线.k-dtree. 卡常啊.空间开1e6就T了. 代码 #include <bits/stdc++.h> #define my_m ...