在日常数据处理过程中避免不了要计算跨长周期数据指标统计需求,类似于如下:

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 (长周期指标) 优化方案的更多相关文章

  1. 数据库SQL优化大总结之 百万级数据库优化方案(转载)

    网上关于SQL优化的教程很多,但是比较杂乱.近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充. 这篇文章我花费了大量的时间查找资料.修改.排版,希望大家阅读之后,感觉 ...

  2. mysql 百万级数据库优化方案

    https://blog.csdn.net/Kaitiren/article/details/80307828 一.百万级数据库优化方案 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 wher ...

  3. 前端项目优化 -Web 开发常用优化方案、Vue & React 项目优化

    github github-myBlob 从输入URL到页面加载完成的整个过程 首先做 DNS 查询,如果这一步做了智能 DNS 解析的话,会提供访问速度最快的 IP 地址回来 接下来是 TCP 握手 ...

  4. C++高并发场景下读多写少的优化方案

    概述 一谈到高并发的优化方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也能很大的影响整体性能,本文从单模块下读 ...

  5. Redmine性能优化方案

    近来公司redmine服务器表现很糟糕,在16核,64GRAM的机器上,压测结果竟然只有每秒5~7个请求,部分页面一个都出不来. 以下是我对Redmine性能优化方案: redmine服务器性能问题排 ...

  6. 移动 H5 首屏秒开优化方案探讨

    转载bang大神文章,原文<移动 H5 首屏秒开优化方案探讨>,此文仅仅用做自学与分享! 随着移动设备性能不断增强,web 页面的性能体验逐渐变得可以接受,又因为 web 开发模式的诸多好 ...

  7. 五个Taurus垃圾回收compactor优化方案,减少系统资源占用

    简介 TaurusDB是一种基于MySQL的计算与存储分离架构的云原生数据库,一个集群中包含多个存储几点,每个存储节点包含多块磁盘,每块磁盘对应一个或者多个slicestore的内存逻辑结构来管理. ...

  8. 从350ms到80ms,揭秘阿里工程师 iOS 短视频优化方案

    内容作为 App 产品新的促活点,受到了越来越多的重视与投入,短视频则是增加用户粘性.增加用户停留时长的一把利器.短视频的内容与体验直接关系到用户是否愿意长时停留,盒马也提出全链路内容视频化的规划,以 ...

  9. 揭秘盒马鲜生 Android 短视频秒播优化方案

    短视频作为内容重要的承载方式,是吸引用户的重点,短视频的内容与体验直接关系到用户是否愿意长时停留.因此,体验的优化就显得尤为重要.上一篇我们分享了 iOS 短视频秒播优化,这篇我们来聊聊 Androi ...

随机推荐

  1. Linux 常用命令(根据自己的理解随时更新)

    1. linux 目录解释系统启动必须: /boot:存放的启动 Linux 时使用的内核文件,包括连接文件以及镜像文件. /etc:存放所有的系统需要的配置文件和子目录列表,更改目录下的文件可能会导 ...

  2. Python的Mixin

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826299.html 一:Mixin模式 Mixin编程是一种开发模式,是一种 将多个不同类中的功能单元的 ...

  3. [TJOI2018]最长上升子序列

    Link 动态维护LIS? 观察题目:在第 i 轮操作时,将数字 i 插入 插入的数字是当前最大的 如果答案与上次不同,新的LIS必以 i 结尾 以 i 结尾的LIS无法再伸长(因为比 i 小的都插入 ...

  4. php调停者模式(mediator pattern)

    差不多了,睡一觉,下次再弄. <?php /* The more classes we have in our software, the more complex their communic ...

  5. opencv想到的

    opencv是用C++写的库,包了多种语言接口,包括C,C++,python,java等. OpenCV 是一个开放源代码的计算机视觉库,目前在科研和开发中被广泛使用.OpenCV 由一系列 C 函数 ...

  6. c小例子 10个数找出第一名

    这个小例子,是从十个数中找到第一名,如果第一名的分数相同,则二者都可以晋级,进入下一轮比赛,我们就对这个数进行排序,这样要求输出晋级人员的标号0-9号中其中一个或几个. 如何用c语言来实现呢? 1) ...

  7. 【PHP】系统部署

    1.MySql数据库,单独创建用户和数据库 使用MySql-Front导入,避免使用Navicat导入 2.httpd-vhosts.conf配置 文件位于:D:\Xampp\apache\conf\ ...

  8. wordpress文章显示同一分类下的上一篇下一篇

    我们在用wordpress开发网站的时候会在文章页中引入上一篇下一篇,但是发现新闻页的上下文章有可能是产品分类的post,这个就不太合理,如何显示同一分类下的上一篇下一篇文章呢?随ytkah一起来看看 ...

  9. 基于原型的js语言

    基于原型编程首先要考虑的问题:原型与对象的关系: 使用原型概念建立基于复用目的的联系链,以供运行时系统使用. 一.原型系统原理 封装.原型.多态 vs 封装.继承.多态 引用原型 vs 复制原型 机制 ...

  10. flux沉思录:面向store和通信机制的前端框架

    一.综述 Flux 被用来描述“单向”的数据流,且包含某些特殊的事件和监听器. 响应式编程是一种面向数据流和变化传播的编程范式 flux是响应式编程的一种? Flux 在本质上采用了模型-视图-控制器 ...