优雅的维度模型与多维分析设计实践
如果无法正常显示,请先停止浏览器的去广告插件。
        
                1. 优雅的维度模型与多维分
析设计实践
邱盛昌-OPPO-技术专家/数据团队主管
DataFunSummit # 2023            
                        
                2. 个人介绍
联系微信号:QiuChanson            
                        
                3. 目录 CONTENT
维度模型设计的必要性 优雅的维度模型设计
解决巨量的取数需求
解决无穷无尽的报表需求
常见的几种错误方向 维表设计
明细表
汇总表
极致分区表的数据仓库架构 万能的多维分析模型与报表
数据源处理
ODS层处理
CDM层处理
ETL架构 Mysql与Clickhouse的区别
多维报表模型
多维分析报表            
                        
                4. 01
维度模型设计的必要性
DataFunSummit # 2023            
                        
                5. 解决巨量的取数需求
 产生巨量需求的本质:数据建设缺失或者建设方向错误,导致大量用数诉求无法满足            
                        
                6. 解决无穷无尽的报表需求
 导致无穷无尽的报表需求原因:通用数据模型设计缺失,面向需求开发无抽象
 首先满足取数需求,才是报表需求
 常用的数据才能被做成报表
 更直观的指标组合与图形可视化
 更方便的报表分析功能(如下钻)            
                        
                7. 常见的几种错误方向
 常见错误方向总结
完全的面向需求开发,需求要什么字段就做什么,一个需求一张RPT表,到处打听到表就直接取用,
逻辑都堆在RPT层
没有模型表,或者模型抽象不好,具体表现为:不了解建模知识,SQL/Java能实现就行;对建模有
些了解,有中间表但通用性较差,没有系统性的全局建模
 没有OLAP建设概念,表拆得又多又散,进入无穷迭代陷阱,如:一个事件做一张事实表
 埋点的“挖矿石”行为,只抽取这个需求要的字段,只做现在要的埋点事件,持续按需求“挖矿”
好几年            
                        
                8. 02
极致分区表的数据仓库架构
DataFunSummit # 2023            
                        
                9. 数据源处理
 埋点元数据:事件元数据
先开发好事件元数据,用于指导主题域划分,模型表的分表和分区等
事件分类ID 事件分类名称 事件ID 事件名称
事件描述
上报数据量 重要程序 负责人
1 曝光 1_1 应用曝光 下载的应用曝光
1200 ★★★★ 张三
1 曝光 1_2 图片曝光 广告图片曝光
980 ★ 张三
2 下载 2_1 列表页下载 在列表页点击下
载按钮 98 ★★★★★ 李四
2 下载 2_2 详情页下载 在详情页点击下
载按钮 71 ★★ 李四
3 启动 3_1 主屏幕启动 在桌面启动应用 550 ★★★ 王五            
                        
                10. 数据源处理
 埋点元数据:字段元数据
字段元数据,用于指导物理表落地建设、字段清洗转换规则等
事件ID
事件名称
字段英文名 字段中文名
字段描述
公共描述
... 从哪个入口带
来的曝光|启动
入口
上报数据量 重要程序 负责人
1200 ★★★★ 张三
1_1 应用曝光 enter_id 从哪个入口带
来的曝光 1_2 图片曝光 app_id 应用ID ... 应用ID 980 ★ 张三
2_1 列表页下载 app_id 应用ID ... 应用ID 98 ★★★★★ 李四
2_2 详情页下载 user_id 用户标识 ... 用户标识 71 ★★ 李四
3_1 主屏幕启动 enter_id 启动入口 ... 从哪个入口带
来的曝光|启动
入口 50 ★★★ 王五            
                        
                11. 数据源处理
 埋点元数据:枚举元数据
枚举元数据,用于指导码值翻译注释,监控、字段清洗转换规则等
枚举标识 枚举标识名称 枚举码 枚举值 上报数据量 重要程序
app_cat 应用分类 1 视频播放 120 ★★
app_cat 应用分类 2 网上购物 110 ★★
app_cat 应用分类 3 社交通讯 100 ★★
from 渠道来源 101 头条 98 ★★
from 渠道来源 102 阿里 90 ★★            
                        
                12. 数据源处理
 补录数据
数据仓库建设中,肯定会有许多的补录数据,必须一开始就约束需求人通过系统录入,补录系统提
供增删改功能,并实现自动导入大数据平台,切记不可工程师手工导入
这样处理补录数据的原因
 减少沟通成本,提高导入效率,提高工程师的幸福感
 保证导入数据的质量,需求人可自助迭代,并可以设置定期提醒补录            
                        
                13. ODS层处理
 开发原则
 缓存层只保留8天数据,只可以被一个ODS表引用
 ODS层不可以当作缓存数据使用,直接抽取数据就到ODS
 多在ODS做join表,而不是在dwd层做,导致dwd层表变多且通用性降低
 有部分表不需要进入CDM层,不需要构建星形模型,则可以在ODS处理直接到应用层            
                        
                14. ODS层处理
 维度穷举实现方法:极致分区表的体现,简洁又省资源            
                        
                15. ODS层处理
 维度穷举的作用
 直接构建维表,在ODS实现,出来的速度非常快
 过滤数据解决数据倾斜问题:
【表A】 左关联【表B】(表B量大无法广播)ON(c1=c2),改造为:
【表A】 左关联【表C】(广播)
【表C】=【表B】内关联【表A.c1的维度穷举表(广播)】            
                        
                16. ODS层处理
 码值翻译
 在ODS层翻译码值 ,统一全局的口径,不可在应用层处处转换
 命名方式:原字段_name(若原字段以id,code结尾则去掉再拼接,如app_id为app_name)
(case
when q.real_style = '0' then
'全屏'
when q.real_style = '1' then
'半屏'
when q.real_style = '2' then
'弹窗'
when q.real_style = '4' then
'小半屏'
else
q.real_style
end) real_style_name            
                        
                17. CDM层处理
 开发原则
事实表:只有需要统一建模才能有cdm,绝不是中间表的概念,是建模的概念(不是为了落一个中
间层方便共用逻辑,而是真正全局的构建星形模型的表)
维表:不是所有表都有资格成为dim表,很多表没有通过抽象与建模也就是个ods,一定要考虑一致
性维度!属于一个维的内容不要有多张表            
                        
                18. CDM层处理
 过滤数据处理
在模型中过滤数据对模型有巨大伤害,新手非常容易犯此错误,举例:
 country='CN' --表中所有数据都是CN的,但这个过滤相当于埋了一个雷,随时会爆
 user_is is not null --看似没用的数据,但可能给你带上枷锁,因为要对数,必须处处带上
 cheat_flag=0 --作弊数据过滤掉,且不说作弊会误判,此条件将会让你查问题异常困难
过滤数据属于个性化逻辑,应该在应用层中处理,模型中切记不可以做任何过滤            
                        
                19. CDM层处理
 公共逻辑处理
当一个逻辑在应用层中出现3次及以上,无论这个逻辑多么小,都应该压在CDM层中处理,举例:
 解开数组或者jason,['app_id'] --看似极小的逻辑,如果你要对app_id做规则,所有地方都要改
 截断字符,substr(str,1,2) --同上,此字段如果在应用层处理,一旦有变化会极其麻烦
 count(1) --非常简单的逻辑,但此处统一了口径,如果在应用层处处count(1),维护成本会非常大
 更多...
应用层一般只做合并、关联或个性化逻辑处理,不做公共逻辑,此条规则一般人很难做到            
                        
                20. CDM层处理
 分区表实现方法
建表
`dt` string comment '分区:日期yyyymmdd',
`df` string comment '分区:事件分类'
代码写法
category_code="${vi_category_code}"
if [ -z "${category_code}" ];then
category_code="others"
condition="and df in ('others')";
else
condition="and df in ('${category_code}')"
fi
insert overwrite table cdo_xxx_dw.ods_cdo_xxx_xxxx_wide_inc_d
partition (dt='${v_day}',df='${category_code}')
select *            
                        
                21. CDM层处理
 分区表实现方法:极致分区表的体现(注意只是一个主题域下的表)
创新方法:只有一个表,一个脚本,一套逻辑,多个调度任务            
                        
                22. ETL架构
 分区表调度方法
优点:
 可维护性好
 不容易出错
 无重复代码拷贝
 分df并行跑,无性能瓶颈
 表少,脚本少
 表好用,无大量union
 只关联一次维表
 省资源,无重复存储
 省资源,无重复计算
 简洁,容易依赖
 调度无等待,谁先好先跑            
                        
                23. ETL架构
 分区的OLAP报表实现方法
优点:
 只需要维护一张ads层的表
 推送按分区,分区越多越快
 CK只有一张表,一张报表
 一张报表配出n张报表
 报表无等待,谁快可先用            
                        
                24. ETL架构
 整体架构
 把分区表运用到出神入化,从ods➜dwd➜dws➜ads➜h2ck一路全是分区表,对于分区表查询,超快超省钱
 所有事件都加入建模,且新事件也自动进到模型,在后继的CDM层的流程中一起处理公共逻辑
 极其优美的三个下划线代表着不同的分区,避免依赖选择困难            
                        
                25. 03
优雅的维度模型设计
DataFunSummit # 2023            
                        
                26. 维表设计
 数据源表的抽象
 抽取涉及维度的所有表所有字段,构造这些表的ER关系图,从ER图抽象出维表
 错误示例:
 抽一张Mysql表就是一张维表,从不考虑整合,还是ER模型
 dim_app,dim_app_v2,dim_ap_v99 --同一个维有多张表
 dim_model,dim_model_detail,--受源系统影响,分段式设计
抽取原则
 抽取这个表的所有字段,不要只挑当前需求要的字段
 抽取表,一个表一个脚本一个任务,不可以一个脚本抽取多个表
 维表保留历史状态,可以采用快照表的方式保留
 抽取完做校验,防止空跑,不然修复成本会非常大            
                        
                27. 维表设计
 数据源表的抽象
尽量做成单一主键的表(但不采用kimball的代理键方式)如下图抽象:
 应用维(含应用分类)
 应用标签表维(微型维)
 应用分类维表(一二三级分类)            
                        
                28. 维表设计
 维表建设重要原则
维表尽可能宽,不管冗余,哪怕超过1000个字段
 码值全映射出来
 非结构化数据全解析出来,如数组,json,map,截断
 所有自定义分类在此定义,如把应用归为头条系,腾讯系
 能在维表沉淀的公共逻辑,不要把逻辑写在事实表中,在维表中统一口径代价更低
强制保证主键唯一,直接在维表代码中做row_number处理            
                        
                29. 明细表设计
 一个主题下只做一个明细表(分区表)
以一个APP上报的所有埋点为例:
 分区df:一般以事件分类为准,建议不要直接取事件ID,长尾影响数据分布
 所有事件理论上全部进明细表,数据量大且冷门的、因成本问题的根据情况来确定
分区:日期dt 分区:数据标识df 事件6+ 头部字段100+ 业务字段600+ 明细map保留
2011-01-01 1 1_1... ... ... ...
2023-11-12 2 1_2... ... ... ...            
                        
                30. 明细表设计
 维度退化
 热门维表的热门字段在明细表全部关联到明细表中
 哪些维度退化极其考验工程师的设计功底,不可贪多,不能太少
 例子说明
 明细表中只有应用版本ID;有应用ID、名称;有应用ID、名称、包名;应用维表热门字段;应用维表所有字段,代表
不同等级维度退化设计
 错误方向:维度还在map/json中的如['app_id'],无法做集成化处理
 错误方向:明细表中只有id,没有中文名,如city_id 没有city_name,每次使用都去关联
 错误方向:只存应用版本ID,SKU_ID等不常用字段,每次使用都要通过桥接表找应用ID,商品ID            
                        
                31. 明细表设计
 二维表化设计
 明细表是一个标准的二维表,字段有原子性,所有非结构化的、二维表化的做法都会带来麻烦
 后端工程师可能更愿意使用json,map,切记不可将这个习惯带到数据领域
 需要改造的例子
 码表翻译,如字段sex_flag里的值:0,1,2,99,加sex_flag_name字段,存映射中文:男,女,其他,未知
 map全解开,如[a:1,b:1]应该解开为两个字段a,b
 json全解开,与map类似,以前听说过一个纯json的数据仓库,所有逻辑用java实现
 聚合上报数据,如'a,b,c,d',根据情况拆解为4条记录            
                        
                32. 汇总表设计
 OLAP表设计
必要先做一张OLAP的dws表,大量非个性化的指标在这里实现
分区:日期dt 分区:数据标识df 事件6+ 头部字段100+ 业务字段600+ 公共指标50+
2011-01-01 1 1_1... ... ... ...
2023-11-12 2 1_2... ... ... ...
必要做一张从OLAP的dws表出的ads层表,作为OLAP报表的底层表
分区:日期dt 分区:数据标识df 事件6+ 筛选后的维度500+ 公共指标50+
2011-01-01 1 1_1... ... ...
2023-11-12 2 1_2... ... ...            
                        
                33. 汇总表设计
 周期快照事实表设计
 周期快照比较常见的是用户画像的实现,就是给用户打标签,实现的逻辑一般比较复杂
 用户标签最好抽象成周期快照事实表,不要放在原子事实表中,不然有可能造成复用度下降
 所有与这个周期快照相关的,最后都应该合并在一个表中,不要过于分散(根据产出时间适当调整)
分区:日期dt 用户标识 年龄 性别 是否高价值用户 总游戏时长 更多字段
2011-01-01 1 ... ... ... ... ...
2023-11-12 2 ... ... ... ... ...            
                        
                34. 汇总表设计
 留存事实表设计
 留存事实表是运营最为常用的事实表之一,一般不会做到OLAP表,形式上是一个梯形
 留存事实表是一个错开日期自关联过程,可以抽象为五要素:用户标签(维度)、前行为时间,前
行为、后行为时间,后行为(前行为与后行为可相同,后行为时间与指标可合并,如打标:是否1,
3,7,14,30天留存)
如果成本允许 ,建议将用户ID也带到报表中,可以配置出千变万化的留存看板,如下例子:
分区:日期dt 用户ID 用户标签 前行为时间 前行为指标 后行为时间 后行为指标
2011-01-01 1 如:机型 ... ... ... ...
2023-11-12 2 如:机型 ... ... ... ...            
                        
                35. 汇总表设计
 归因事实表设计
 归因事实表是运营最为常用的事实表之一,一般不会做到OLAP表,形式上是一个漏斗
 比如一个典型归因的过程:启动➜曝光➜下载➜打开➜访问页面➜下单
 归因的各种方法:参数归因、离线字段匹配归因(有损)、实时数据流中染色打标
 归因事实表非常复杂,计算量巨大,容易产生性能问题,很考验工程师的技术水平
 归因路径组合较多,需要与业务充分沟通,选择确定好场景,在dws层预先计算出来
 合并事实表与归因事实表区别:            
                        
                36. 04
万能的多维分析模型与报表
DataFunSummit # 2023            
                        
                37. Mysql与Clickhouse的区别
 Mysql表的问题
 大数据量报表查询缓慢,使得开发者报表拆得太细做得过多,程序分散,维护困难,人效低
 Mysql数据库整体容量太小,经常满,经常要清理和迁移,运维成本大
 大部分人不会使用分区表,推数粗暴导致推送主从延迟严重,被迫读写都使用主库
 与Hadoop集群的Sqoop工具搭配使用时权限管理非常困难,经常报权限问题            
                        
                38. Mysql与Clickhouse的区别
 Clickhouse解决的问题
 快!
 可搭建空间非常大的集群
 无主从延迟烦恼,无权限烦恼,吞吐量大,推送数据快
 99%的报表都可以使用CK做为载体,稳定性好,无卡死,锁之类的问题
 天然支持TTL生命周期,从规范上限定所有表都有TTL,自动实现数据治理,防止先污染再治理
 支持近似计算,使用uniq(imei)替代count(distinct imei),获取性能优势            
                        
                39. 多维报表模型
 多维报表模型            
                        
                40. 多维分析报表
 多维分析报表
 提供一个报表解决80%+的数据获取问题
 70%的报表可以从一张报表配置衍生出来,不需要开发代码,不需要发版本,运营也可以实现配置
 大量报表的底层表都是OALP表,只需要维护一张表
 基于Clickhouse直接自助查询CK表,可以秒出,效率提升几百倍
 为平衡成本,保证历史数据的获取,可以制定多版本:            
                        
                41. 感谢观看