数仓开发过程(开发向)
Posted 终回首
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数仓开发过程(开发向)相关的知识,希望对你有一定的参考价值。
一、需求调研
需求调研的分析产出通常是记录原子与派生指标的文档。
1 确定需求
1.1 业务调研
业务调研是数据仓库的基础。
业务调研需要开发人员找需求方和业务人员包括业务系统的产品经理、业务系统开发人员了解业务,获取相关文档。沉淀出相关文档。具体文档应当包括以下信息:
-
用户的组织架构和分工界面。
例如,用户可能分为数据分析、运营和维护部门人员,各个部门对数据仓库的需求不同,您需要对不同部门分别进行调研。 -
用户的整体业务架构,各个业务板块之间的联系和信息流动的流程。
您需要梳理出整体的业务数据框架。 -
各个已有的业务板块的主要功能及获取的数据。
以A公司的电商业务为例,梳理出业务数据框架如下图所示。A公司的电商业务板块分为招商、供应链、营销和服务四个模块,每个板块的需求和数据应用都不同。
构建数据仓库之前,首先需要明确构建数据仓库的业务板块和需要具体满足的业务需求。
此外,还需要进一步了解各业务板块中已有的数据功能模块。数据功能模块通常和业务板块紧耦合,对应一个或多个表,可以作为构建数据仓库的数据源。下表展现的是一个营销业务板块的数据功能模块。
数据功能模块 | A公司电商营销管理 |
---|---|
商品管理 | Y |
用户管理 | Y |
购买流程 | Y |
交易订单 | Y |
用户反馈 | Y |
1.2 确定需求
假设用户是电商营销部门的营销数据分析师。
数据需求为最近一天某个类目(例如,厨具)商品在各省的销售总额、该类目Top10销售额商品名称和各省客户购买力分布(人均消费额)等,用于营销分析。
最终的业务需求是通过营销分析完成该类目的精准营销,提升销售总额。通过业务调研,我们将着力分析营销业务板块的交易订单数据功能模块。
了解与分析需求的2种途径:
- 根据与分析师和业务运营人员的沟通获知需求。
- 对报表系统中现有的报表进行研究分析。
在确定需求时要沉淀出业务分析或报表中的指标,以及指标的定义和粒度。之后可以根据粒度产生维度,再根据与需求方沟通得出最终的维度。
- 业务数据是根据什么(维度、粒度)汇总的,衡量标准是什么?例如,昨日是维度,订单数是昨日维度对应的度量。
- 明细数据层和汇总数据层应该如何设计?公共维度层该如何设计?是否有公共的指标?
- 数据是否需要冗余或沉淀到汇总数据层中?
确定需求总结:
2 分析业务过程
业务过程可以概括为一个个不可拆分的行为事件。用户的业务系统中,通过埋点或日常积累,通常已经获取了充足的业务数据。为理清数据之间的逻辑关系和流向,首先需要理解用户的业务过程,了解过程中涉及到的数据系统。
可以采用过程分析法,将整个业务过程涉及的每个环节一一列清楚写在文档里,包括技术、数据、系统环境等。
在分析企业的工作职责范围(部门)后,也可以借助工具通过逆向工程抽取业务系统的真实模型。
可以参考业务规划设计文档以及业务运行(开发、设计、变更等)相关文档,全面分析数据仓库涉及的源系统及业务管理系统:
- 每个业务会生成哪些数据,存在于什么数据库中。
- 对业务过程进行分解,了解过程中的每一个环节会产生哪些数据,数据的内容是什么。
- 数据在什么情况下会更新,更新的逻辑是什么。
业务过程可以是单个业务事件,例如交易的支付、退款等;也可以是某个事件的状态,例如当前的账户余额等;还可以是一系列相关业务事件组成的业务流程。具体取决于您分析的是某些事件过去发生情况、当前状态还是事件流转效率。
选择粒度:在业务过程事件分析中,需要预判所有分析需要细分的程度和范围,从而决定选择的粒度。
识别维表、选择好粒度之后,需要基于此粒度设计维表,包括维度属性等,用于分析时进行分组和筛选。
分析业务过程总结:
3 划分数据域(主题域)
数据域是联系较为紧密的数据主题的集合,是业务对象高度概括的概念层次归类,目的是便于数据的管理和应用。划分数据域就是将数据按照业务过程的抽象分类的过程。
通常需要阅读各源系统的设计文档、数据字典和数据模型设计文档,研究逆向导出的物理数据模型。进而,可以进行跨源的主题域合并,跨源梳理出整个企业的数据域。
数据域是指面向业务分析,将业务过程或者维度进行抽象的集合。为保障整个体系的生命力,数据域需要抽象提炼,并长期维护更新。
在划分数据域时,既能涵盖当前所有的业务需求,又能让新业务在进入时可以被包含进已有的数据域或扩展新的数据域。数据域的划分工作可以在业务调研之后进行,需要分析各个业务模块中有哪些业务活动。
划分方式:
- 按业务过程或者业务板块分,自下而上
- 按照用户企业的部门划分,自上而下
- 按数据需求方划分
例如A公司电商营销业务板块可以划分为如下数据域,数据域中每一部分都是实际业务过程经过归纳抽象之后得出的。
电商数据域划分:
数据域 | 业务过程 |
---|---|
会员店铺域 | 注册、登录、装修、开店、关店 |
商品域 | 发布、上架、下架、重发 |
日志域 | 曝光、浏览、点击 |
交易域 | 下单、支付、发货、确认收货 |
服务域 | 商品收藏、拜访、培训、优惠券领用 |
采购域 | 商品采购、供应链管理 |
4 确定维度与构建总线矩阵
明确每个数据域下有哪些业务过程后,需要开始定义维度,基于维度构建总线矩阵。
在划分数据域、构建总线矩阵时,需要结合对业务过程的分析定义维度。以A电商公司的营销业务板块为例,在交易数据域中,我们重点考察确认收货(交易成功)的业务过程。
4.1 确定维度
在确认收货的业务过程中,主要有商品和收货地点(本教程中,假设收货和购买是同一个地点)两个维度所依赖的业务角度。从商品维度我们可以定义出以下维度的属性:
- 商品ID(主键)
- 商品名称
- 商品交易价格
- 商品新旧程度: 1 全新 2 闲置 3 二手
- 商品类目ID
- 商品类目名称
- 品类ID
- 品类名称
- 买家ID
- 商品状态: 0 正常 1 删除 2 下架 3 从未上架
- 商品所在城市
- 商品所在省份
从地域维度,我们可以定义出以下维度的属性:
- 城市code
- 城市名称
- 省份code
- 省份名称
作为维度建模的核心,在企业级数据仓库中必须保证维度的唯一性。以A公司的商品维度为例,有且只允许有一种维度定义。例如,省份code这个维度,对于任何业务过程所传达的信息都是一致的。
4.2 构建总线矩阵
明确每个数据域下有哪些业务过程后,即可构建总线矩阵。需要明确业务过程与哪些维度相关,并定义每个数据域下的业务过程和维度。
如下所示是A公司电商板块交易功能的总线矩阵,我们定义了购买省份、购买城市、类目名称、类目ID、品牌名称、品牌ID、商品名称、商品ID、成交金额等维度。
5 明确统计指标
需求调研输出的文档中,含有原子指标与派生指标,此时我们需要在设计汇总层表模型前完成指标的设计。
原子指标和派生指标
原子指标用于明确业务的统计口径和计算逻辑,是基于用户的业务活动(即业务过程)创建的,用于统计业务活动中某一业务状况的数值。例如,用户的业务活动为购买,则原子指标就可以指定为支付金额。
派生指标是由原子指标、时间周期、修饰词构成,用于反映企业某一业务活动在指定时间周期及目标范围中的业务状况。例如,某企业近一周上海地域的销售金额。
原子指标文档 参考:
字段 | 描述 |
---|---|
指标编号 | 该指标唯一标识,建议自动生成 |
业务过程 | 原子指标所属的业务过程。 |
英文缩写 | 原子指标的英文缩写。英文缩写是指标的唯一性标识。英文缩写由小写英文字母、数字、下划线(_)组成,并且以小写英文字母开头。 |
英文名称 | 原子指标的英文名称。建议使用原子指标所统计数值的英文,便于您快速了解该原子指标的统计类型。英文名称由英文字母、数字、下划线(_)、and(&)组成,并且以英文字母或数字开头。 |
中文名称 | 原子指标的中文名称。建议使用原子指标所统计数值的中文,便于快速了解该原子指标的统计类型。中文名称由中文、英文字母、数字、下划线(_)、and(&)、英文括号组成,并且以中文、英文字母或数字开头。 |
业务口径 | 用于统一原子指标所统计的业务活动的统计口径,防止统计时产生歧义。例如,下单实际支付金额的业务口径为:用户下单生成订单后,通过支付渠道支付了订单金额的总和。该金额为扣除掉所有红包优惠后,用户实际支付的金额总和。 |
描述 | 原子指标的描述信息。 |
派生指标文档 参考:
字段 | 描述 |
---|---|
指标编号 | 该指标唯一标识,建议自动生成 |
数仓分层 | dws或ads |
中文名称 | 派生指标的中文名称,由中文、英文字母、数字、下划线(_)、and(&)、英文括号组成,并且由中文、英文字母或数字开头。 |
英文名称 | 派生指标的英文名称。由英文字母、数字、下划线(_)、and(&)组成,并且以英文字母或数字开头。 |
时间周期 | 业务活动数值统计的时间范围。例如,近一天,近一周。 |
修饰词 | 业务活动数值统计的范围限定。例如,线上、线下。 |
原子指标 | 该派生指标来源的原子指标的编号。用于确定目标业务活动及其统计数值的计算逻辑。例如,下单金额。 |
关联维度 | 用于确定具体业务活动需要分析的维度。例如,商品维度、商家维度。生成改派生指标必须关联的维度。 |
描述 | 派生指标的描述信息。 |
假设数据需求为最近一天厨具类目的商品在各省的销售总额、该类目Top10销售额商品名称、各省用户购买力分布(人均消费额)等,用于营销分析。
根据之前的分析,我们确认业务过程为:确认收货(交易成功),而度量为商品的销售金额。因此根据业务需求,我们可以定义出原子指标:商品成功交易金额。
派生指标为:
- 最近一天全省厨具类目各商品销售总额
- 最近一天全省厨具类目人均消费额(消费总额除以人数)
最近一天全省厨具类目各商品销售总额进行降序排序后取前10名的名称,即可得到该类目Top10销售额商品名称。
二、方案设计
1 数据探查
数据探查的目的是了解数据的形态,找到潜在问题与风险。数据探查是决定数据可靠性的关键步骤。数据探查报告可以为后续开发提供指导,并作为依据指定开发计划。
数据探查的内容主要包括但不限于以下内容:
- 源表数据主键字段重复数。
- 源表字段空值/异常值的统计数。
- 源表之间关联关系。
- 源表之间的关联字段。
- 源表字段的数据格式。
- 源表增量规则。
探查完成后,最终产出数据探查报告。如果发现当前数据无法支撑需求的实现,则要将需求退回给数据产品经理或需求方,由数据产品经理或需求方发起迭代需求流程。
数据探查报告模板
字段顺序 | 字段名 | 字段注释 | 字段类型 | 总行数 | 空值个数 | 空值比例 | 唯一个数 | 均值(number) TOP1(string) | 最小值/TOP2 | 1%分位数/TOP3 | 25%分位数/TOP5 | 中位数/BOT5 | 75%分位数/BOT4 | 95%分位数;BOT3 | 99%分位数;BOT2 | 最大值;BOT1 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
- TOP N 前几
- BOT N 后几
2 开发设计
开发设计包括三个部分:DDL表设计、DML设计。
2.1 DDL表设计
表设计是指依据需求设计目标产出表、中间产出表。包含表名、表名解释、字段名、字段类型、字段注释以及字段安全等级等。表设计的步骤如下所示:
- 设计表名、字段名:要求相同的字段在不同表中的字段名相同。
- 设计主键和外键。
- 设计字段注释:通过标注字段注释、枚举值来表明字段含义,如果枚举值过多,建议为枚举值创建维表。
- 设计表分区:建议所有表都创建为分区表。
- 设计数据生命周期。
- 设计加密技术:根据实际情况对敏感字段设计加密方案。
数据生命周期应该根据具体业务具体场景确定。
数仓分层 | 说明 |
---|---|
ODS层 | 非去重数据:默认不保留;ETL临时表:保留14日;镜像全量表:重要数据建议采用极限存储;流水全量表:如果不可再生,则永久保存。 |
DWD层 | 维度表:按日分区的极限存储模式;事实表:按日分区且永久保留;流水全量表:周期性快照事实表:采用极限存储或根据自身情况设置生命周期。 |
ODS层 | 汇总指标:自行选择保留月初、特定日期数据。 |
2.2 DML设计
编写规划以下内容:
- 每个字段的生成逻辑。
- 表与表之间的关系。
- 目标字段与原字段间的算法逻辑。
上述内容产出为ETL文档
示例表
表名 | 说明 |
---|---|
ods_raw_log_d | 离源ODS层最近的数据 |
dwd_user_info_d | 用户公共明细表 |
dws_user_info_d | 用户公共汇总表 |
dm_user_info_d | 用户数据集市表 |
rpt_user_info_d | 用户分析汇总表 |
ETL文档示例:
字段名称 | 目标表字段 | 字段说明 | 源表 | 涉及源表字段 | 算法说明 | 备注 |
---|---|---|---|---|---|---|
uid | 用户ID | 用户ID | ods_log_info_d | uid | 抽取汇总 | |
gender | 性别 | 性别 | ods_log_info_d | time | 抽取 | |
age_range | 年龄段 | 年龄段 | ods_log_info_d | status | 抽取 | |
zodiac | 星座 | 星座 | ods_log_info_d | bytes | 抽取 | |
region | 地域,根据IP获取 | 地域,根据IP | ods_log_info_d | region | 转换 | |
device | 终端类型 | 终端类型 | ods_log_info_d | method | 抽取 | |
identity | 访问类型 crawler feed user unknown | 访问类型 crawler feed user unknown | ods_log_info_d | URL | 抽取 | |
method | HTTP请求类型 | HTTP请求类型 | ods_log_info_d | protocol | 抽取 | |
URL | URL | URL | ods_log_info_d | referer | 截取引用IP | |
referer | 来源URL | 来源URL | ods_log_info_d | device | 截取设备名称 | |
time | 时间yyyymmddhh:mi:ss | 时间yyyymmddhh:mi:ss | ods_log_info_d | identity |
- 这里的算法说明要详细具体
2.3 调度设计
依赖设计
将ETL抽象为多个相互依赖的代码节点形成上下游依赖关系,要求如下:
一个节点仅产出一张表,一张表仅由一个节点产出。
下游节点的输入数据来自于上游节点的产出数据。
多并行、少串行(在分布式系统下可发挥其优势)。
运行周期
如果数据研发的场景是在常见T+1离线计算场景,则应将不同调度任务按照实际业务需求,赋予小时、日、周、月和季度等不同的调度粒度。
设置基线
在传统T+1(每日计算的是前一日产生的业务数据)的场景下,数据理应在第二天某个时间点按时产出以支撑BI或其他应用场景,因此应设置如下基线报警策略。
- 最终产出任务基线:规定产出最终数据的任务必须在公司规定的X点X分完成,否则视为破线(同时推送相应报警)。
- 中间任务报警:产出最终数据的任务的上游任务应稳定、按时运行完成。如果出现出错、变慢(运行时间明显长于历史过往平均运行时间)等可能影响最终任务完成时间的事件,则应第一时间推送报警给第一任务责任人。
设置优先级
基于有限的计算资源来设置任务优先级,以保证在已有资源被充分调配利用的情况下,可以按照顺序产出数据,保证重要任务的准时产出。调度设计完成后,需要产出调度设计文档。
调度设计文档参考:
节点ID | 节点名称 | 用途 | 数据输入表 | 数据产出表 | 调度周期 | 定时时间 | 预计运行时间 | 上游节点ID | 上游节点名称 | 基线时间 | 优先级 |
---|---|---|---|---|---|---|---|---|---|---|---|
320170260 | mysql数据同步 | 拉取MySQL数据源数据 | ods_user_info_d | ods_user_info_d | 日 | 00:03 | 1mins | 320170257 | workshop_start | Null | 1 |
320170260 | FTP数据同步 | 拉取FTP数据源数据 | Null | ods_raw_log_d | 日 | 00:03 | 1mins | 320170257 | workshop_start | Null | 1 |
320170261 | ods_log_info_d | 原始数据脏数据清理 | ods_raw_log_d | ods_log_info_d320170259 | 日 | 00:05 | 10mins | 320170260/320170259 | MySQL数据同步/OSS数据同步 | Null | 1 |
320170262 | dw_user_info_all_d | 轻度汇总数据 | ods_log_info_d | dw_user_info_all_d | 日 | 00:20 | 5mins | 320170261 | ods_log_info_d | Null | 1 |
320170263 | rpt_user_info_d | 统计汇总报表数据 | dw_user_info_all_d | rpt_user_info_d | 日 | 00:30 | 30s | 320170262 | dw_user_info_all_d | 0:40:00 | 1 |
数据流设计
ETL过程中,数据流向有如下限制:
- 数据流向仅支持由低到高,即ODS->DWD->DWS->ADS。
- 数据不能跨层引用且不能逆向引用。
- DWS层不同集市的数据不能相互引用,必须沉淀到DWD层。
三、数据开发
1 代码开发
编码时需要注意以下规范:
- 增加必要注释,以增强代码的可读性。
- 充分考虑执行速度最优的原则。
- 必须提交已格式化的代码。
- 不建议使用select *操作,所有操作必须明确指定列名。
- 所有产出表都需要有物理主键或逻辑主键,并纳入周期性数据质量监控。
2 单元测试
代码开发完成后,开发人员需要对代码进行单元测试,单元测试阶段包括以下内容:
- 规范性检查。
- 代码质量检查:建议单条SQL执行时间不超过30分钟。
- 数仓特殊需求检查。
- 指标特性检查。
单元测试完成后,需整理输出单元测试报告和发布操作文档,以便开展后续发布工作。
测试类别 | 测试要点 | 说明 | 是否已检查(Y/N) |
---|---|---|---|
规范类 | 命名规范检查(表、视图、工作流、字段) | 是否符合公司数仓规范规定的表命名规范 | |
规范类 | 代码格式和注释规范性 | 提交的代码是否格式化,所有的计算字段是否有详细具体的注释 | |
规范类 | 表引用规范性 | 数据不允许跨层引用。 | |
规范类 | 表更新策略规范 | 临时表均为非分区表,正式表均为分区表。 | |
规范类 | 是否支持重跑 | 代码必须支持重跑。 | |
源数据质量 | 非空值检查 | 检查所用字段是否存在空值,以及代码对空值处理的策略是否正确。 | |
源数据质量 | 字段枚举值检查 | 字段的枚举值是否都在代码考虑范围内,是否有可能会出现新值。 | |
源数据质量 | 主键检查 | 物理主键或逻辑主键是否成立。 | |
源数据质量 | 数据完整性检查 | 代码中引用的数据能否支撑实际需求。 | |
源数据质量 | 字段间逻辑检查 | 字段间的业务逻辑关系是否在数据上成立,例如余额=总的发放-总的回收。 | |
源数据质量 | 非空值检查 | 检查所用字段是否存在空值,以及代码对空值处理的策略是否正确。 | |
源数据质量 | 字段枚举值检查 | 字段的枚举值是否都在代码考虑范围内,是否有可能会出现新值。 | |
源数据质量 | 主键检查 | 物理主键或逻辑主键是否成立。 | |
源数据质量 | 数据完整性检查 | 代码中引用的数据能否支撑实际需求。 | |
源数据质量 | 字段间逻辑检查 | 字段间的业务逻辑关系是否在数据上成立,例如余额=总的发放-总的回收。 | |
代码质量/BUG检查 | 历史拉链表检查断链/交叉链 | 使用标准SQL进行检验。 | |
代码质量/BUG检查 | 数据倾斜检查 | 是否存在倾斜的情况,是否有大表join小表未用mapjoin等。 | |
代码质量/BUG检查 | 关联条件检查 | 关联条件是否正确,是否会产生意料外的结果,例如多对多关联、笛卡尔积。 | |
代码质量/BUG检查 | 字段类型检查 | 字段类型是否正确,例如:金额字段必须为X数据类型,编号字段必须为X数据类型。 | |
代码质量/BUG检查 | 字段间逻辑检查 | 字段间的业务逻辑关系是否在数据上成立,例如余额=总的发放-总的回收。 | |
代码质量/BUG检查 | 执行效率检查 | 单条SQL执行时间不超过30分钟,单个脚本执行时间不超过60分钟。 | |
数仓特殊需求 | 脏数据检查 | 检查是否有脏数据。 | |
数仓特殊需求 | 增量/全量数据抽取规范 | 抽取时间大于X分钟的,则考虑更改为增量抽取。 | |
数仓特殊需求 | 数仓抽取时间点检查 | 数仓抽取时业务系统是否ready,抽取的数据是否完整。 | |
指标特性检查 | 细分指标趋势检查 | 例如会员拉链表记录数相比前一天必须是正增长、当日累计值-上日累计值必须大于0。 | |
指标特性检查 | 不同粒度数据转换正确性 | 例如细粒度向粗粒度汇总,通常使用最大/最高/最小/最低等过滤条件,如:支用层逾期天数转换到客户层指标(最高逾期天数)。最高逾期天数 = Max(支用层逾期天数)。 | |
指标特性检查 | 值域范围检查 | 检查字段值的范围是否正确,如:金额>=0,比率<=1,天数<=业务起始日期至今,还款日期>=放款日期。 | |
指标特性检查 | 代码值分布检查 | 从业务逻辑考量字段值的分布情况是否合理。 | |
指标特性检查 | 可累加值与不可累加值检查 | 检查可累加值和不可累加值的处理逻辑正确性,如:计算客户数总计时需要做去重处理,金额则可以累加。 |
单元测试用例记录文档:
序号 | 用例大类 | 测试要点 | 表 | 字段 | 自定义表达式 | 备注 |
---|---|---|---|---|---|---|
1 | 规范性 | 命名规范检查(表、视图、工作流、字段) | jrcdm_agt_ovd_ins_detail_fact_dd | |||
2 | 规范性 | 是否支持重跑 | jrcdm_agt_ovd_ins_detail_fact_dd | |||
3 | 源数据质量 | 主键检查 | afclms_clms_loan_contract | contract_no | ||
4 | 指标特性检查 | 值域范围检查 | jrcdm_cust_drawndn_fact_ds | prin_max_ovd_days, inte_max_ovd_days | prin_max_ovd_days>=inte_max_ovd_days | 检验逾期天数的业务逻辑。 |
5 | 指标特性检查 | 值域范围检查 | x_jredw_da_drawndn_ovd_date_info | Prin_Ovd_Start_Dt | Prin_Ovd_Start_Dt<=Prin_Ovd_End_Dt, Inte_Ovd_Start_Dt <=Inte_Ovd_End_Dt | 检查业务逻辑正确性。 |
测试结果 | 测试结果备注 | 是否转化监控 | 监控阈值 | 创建日期 | 创建人 | 所属项目名称 |
---|---|---|---|---|---|---|
通过 | 2013/7/16 | XXX | 某项目 | |||
通过 | 2013/7/16 | XXX | 某项目 | |||
通过 | 2013/7/16 | XXX | 某项目 | |||
通过 | 是 | <1 | 2013/7/16 | XXX | 某项目 | |
未通过 | 开发代码中存在以下两个问题:1 未对期次还款日大于当前日期的记录进行过滤,这部分为未到期记录,需要排除。2 未对记录中创建时间小于期次还款日的、未结清的期次记录的逾期结束时间,赋予与 以上是关于数仓开发过程(开发向)的主要内容,如果未能解决你的问题,请参考以下文章 |