跳到主要内容

数仓架构体系

· 阅读需 20 分钟

分层定义

为什么要分层?

  • 清晰数据结构
  • 数据血缘追踪
  • 减少重复开发
  • 把复杂问题简单化
  • 屏蔽原始数据的异常
  • 屏蔽业务的影响

层级划分

ODS 数据来源层

数据来源层,主要包含业务数据库快照数据(db)、埋点数据(data)、其他业务等数据。

数仓模型层:

TMP:临时层, 数据处理的辅助处理层,服务于DW、DM层,主要是一些临时存储的数据,根据实际情况选择创建与不创建,包括:计算任务的中间结果数据、RAW层每日增量数据抽取临时落地等,一般最多保存1-2天即可清理。

DIM:维度数据层,主要包含一些字典表、维度数据。实例:品类字典表、城市字典表、渠道字典表、终端类型表、支付状态表、圈子列表

DW:data warehouse,存储经过标准规范化处理(即数据清洗)后的运营数据,是基础事实数据明细层。实例:后端日志明细表、前端埋点日志明细表、mysql各业务数据经过ETL处理后的表。

DWS:轻度汇总层,基于单事实表进行指标轻度加工。

DM:data market(也叫DWS:data warehouse service),数据主题层或者宽表层,按部门按专题进行划分,支持OLAP分析、数据分发等,其信息主要来源于DW 或TMP层汇总数据。实例:新激活用户业务分析表、日活用户业务分析表、历史激活用户业务分析表、用户行为轨迹表、红包业务表、交易品类来源多维表、商业广告多维分析报表

应用数据层

ADS:application database service,应用数据层, 面向具体应用的表,要创建在这层,可导入hbase或mysql等使用。实例:按天、小时、5分钟粒度计算汇总的结果存入mysql、hbase的报表

数据流向

  • 数据单向加工不可逆
  • 除图里标注的流向外数据不可跨层调用

image

数仓搭建思路

  • 所有数据的贴源层表都存放在 业务global 即可,业务线不需要单独维护业务线自己的贴源层。
  • 所有数据源进数仓首要要落地到ods层,不可跳过贴源层在其他层直接落地和使用(手工配置表除外) 。
  • 所有从数仓出去的表必须在ads首先落地,才能对外输出。
  • 全局基础数据放在 global(如订单、商品、用户模型表等)下,功能包括:全局数据、清洗脏数据等
  • 根据实际业务情况,业务线数据库重新定义B2C/B2B/C2C/C2B 4条,数据仓库的库单独维护,即 dw_b2c/b2b/c2c/c2b,其他业务线放在GLOBAL下即可(搜索推荐、商业等有自主搭建数仓能力的仍然是自己维护,暂时不做管控)
  • 全局/业务线的沉淀大宽表、专题表、指标表放在 dm_global/b2c/b2b/c2b/c2c
  • dm_global不可用不同业务线的数据的dm层,需global自己加工(目的是为了让全局有业务沉淀,有自主数据加工能力)
  • 分析结果表放在 ads_global/b2c/b2b/c2b/c2c
  • ads_global可组合不同业务线的数据的dm,ads层(为的是快速响应业务需求,同时个性化业务需求没必要在全局层面保留)
  • 注意:对于已固化的业务:先放在global,业务线从global获取数据;对于新业务或探索性业务:先在业务线数仓满足诉求或搭建模型,待业务稳定后再完善global)

业务板块划分

业务分全局业务和各业务线

  • 建设要求 优先建设全局业务板块,特殊场景下可以按业务线建设具体的业务线板块

  • 命名规则

全局为 global

各业务线 b2b c2c等

具体如下:

odsdb_global 从公司各业务mysql表以及其他数据源 同步的快照信息;从日志读取的原始日志数据 dw_global 包含公司各业务经过ETL后的基础事实明细表和轻度汇总表 dim_global 包含公司所有的字典信息和维度表 dm_global 面向公司的不同主题业务的公共分析数据(日活、交易、用户标签等) ads_global 面向公司的不同主题业务的结果分析数据,可用于BI展示、推送、分析等使用 tmp_global 包含基于公司层面分析产生的一些临时表

各业务线类似

总线矩阵划分规则(DW)

  • 总线矩阵:在企业范围内具有统一解释的标准化维度与事实的一整套数据体系,所有业务创建的维度模型共享一组具有一致性的共用综合维度。
  • 一致性维度:维度同一,具有一致的维度关键字、一致的属性列名字、一致的属性定义以及一致的属性值。
  • 数据域:将所有的业务过程进行聚类,高度抽象后形成的一个分析主题。主要参考2个原则1个思想设计:
  • 第一原则:高内聚低耦合,将概念接近,关联度高的放在一类。
  • 第二原则:保证抽象逻辑的一致性,形成最终的数据域和相关业务过程。
  • 一个思想:螺旋递进,数据域的划分没有完美的状态,只有接近完美,在实践过程中以螺旋递进的方式迭代优化。 常见的抽象方法:
  • 按业务或业务过程划分:比如销售、回收、租赁。
  • 按需求方划分:比如需求方为财务部,就可以设定对应的财务主题域,而财务主题域里面可能就会有员工工资分析,投资回报比分析等主题;
  • 按功能或应用划分:比如履约能力、营销活动等
  • 按部门划分:比如商业广告、风控

一致性维度 : 日期 平台 终端 终端版本号 渠道 业务线 品类 品牌 型号 城市 设备id 用户id 商品id 销售id 等

数据域(一级子域(二级子域)) :

交易 (交易( 线上,线下 )) 履约 (客服( 会话,外呼,直播 )) 商品 (供给( 线下)) 营销 (私域,新媒体,红包)

业务过程举例

客服 --- 会话 ---- 用户进线,机器人接待,用户转人工,用户评价,客服创建工单,处理工单

数据主题域划分规则(DM)

DM层用于建设跨主题宽表、跨主题汇总表、项目或专题级基础表

DM数据主题域是根据业务看数据的方式制定,如需新增联系对应负责人

一级主题

channel 渠道 finance 财务 price 价格系统 user 用户 scm 供应链 recommend 搜索推荐 afs 售后 spam 风控

应用主题域划分规则(ADS)

ADS层是应用层,基于应用层的多样化,此处制定ADS层的应用主题命名规范,便于快速识别数据的使用形式。

bi 分析报表使用 ads_bi_ei_type_pur_online_sum_inc_1d “bi”占据第二位,如有数据域,数据域放在第三位

ana 分析师自主分析专用

app app客户端推送使用,其他业务部门数据库推送使用。

开发流程规范

开发流程需遵循 开发流程规范,新建表规范,表权限规范,脚本规范,调度规范,监控规范,报表下线规范,生命周期管理规范

总体流程为

业务调研 -> 模型设计 -> 模型评审 -> 模型开发 -> 模型自测 -> 上线审核

业务调研: 业务调研重点在于搞清楚涉及到的业务板块、数据域、业务过程,以及梳理需要看数据的维度和重点关注的指标。为后续模型设计提供参考。可酌情产出mrd文档、prd文档,暂不做强制要求。

模型设计: 模型设计应遵循数仓架构体系中对数据加工流向,结合业务调研的结果和总线矩阵的规划,优先进行DW层的事实表和DIM维表设计,其次进行DM层模型设计。

image

模型评审: 重点对规范执行情况、是否重复建设、设计是否全面富有前瞻性、维度设计是否合理进行评审,是模型开发前的第一道把控。

image

模型开发: 模型开发应遵循建表规范、表权限规范、脚本规范、调度规范、监控规范、报表下线规范、生命周期管理规范等规范。

image

模型自测: 模型自测是上线前对模型的数据质量、粒度等进行检验,是必须执行的一个环节,自测文档暂不做强制要求,二期再补充完善。

image

模型上线: 模型上线需要在数仓地图进行注册,注册需维护模型的基本信息,如所属业务板块、数据域、业务过程、粒度、事实属性、维度、度量、使用说明等等。数仓地图作为模型对外的出口,解决找表难问题的同时,注册审核通过方能上线的机制,也是数仓规范落地情况的最后一道屏障。

详细模型注册规范可查看 数仓地图模型注册规范。

image

设计文档模板

DW事实表示例说明

模型表 表中文名 业务板块 数据域 业务过程 模型表注释 表主键/粒度 生命周期 使用说明 跑数方式 主要来源表 表名 别名 关联条件 备注

  • 每个字段说明如下:

序号 分类 目标字段 字段类型 字段注释 数据逻辑

DW维度表示例说明如上

DM集市表同上

新建表规范

每层是一个单独库

分层库库名:xxxx

各层存储形式:

数仓层级 表类型 存储格式 ods 默认(管理表) 默认(TEXTFILE) dim 外部表 PARQUET dw 外部表 PARQUET dm 外部表 PARQUET tmp 默认(管理表) 默认(TEXTFILE) ads 默认(管理表) 默认(TEXTFILE)

贴源层表命名规范

1 数据源是mysql,使用sqoop离线抽数的:

表命名规则:odsmysql{源数据库名}{源数据库表名}{增全量}_{调度频率} 。命名分为四部分:

第一部分为数据仓库分层的区分,数据准备区命名为raw;

第二部分为数据源类型;

第三部分{源数据库名}为源数据库名,可以保证数据准备区库的相对稳定,建立与源库库名对应关系。此项避免不同源数据库存在相同表名情况

第四部分{源数据库表名}为源数据库表名,所有表表名与源表表名保持一致

第五部分对应表名后缀规则,见 建表规范。

比如panda库pdi_product表对应ods库命名为:ods_mysql_panda_pdi_product_full_1d 。

2 数据源是mysql,使用实时平台抽取的:

hdfs元数据全部存放在 odsdb_global.ods_cdc_binlog_ori_inc_1h ,需要从该表抽取解析出单表的小时分区数据,如需要,再次加工为全量表。

表命名规则:rawmysql{源数据库名}{源数据库表名}{增全量}_{调度频率} 。

比如 odsdb_global.ods_cdc_binlog_ori_inc_1h → ods_mysql_panda_pdi_product_inc_1h (dt='yyyy-MM-dd')(当天数据做merge)→ ods_mysql_panda_pdi_product_full_1h (dt='yyyy-MM-dd')(当天数据和历史所有数据做merge)。

3 数据源是Tidb库:

表命名规则:odstidb{源数据库名}{源数据库表名}{增全量}_{调度频率} 。

比如: ods_tidb_tdb_zzinfoarchived_t_info_ext_archived_full_1d 。

4 数据源是日志:

表命名规则:odslog日志平台或来源{自定义表名}{增全量}_{调度频率} 。

比如 ods_log_sensors_bury_cold_inc_1d 。

5 数据源是es/mongo/redis/hbase/mq:

表命名规则:odses/mongo/redis/hbase/mq{自定义表名}{增全量}{调度频率} 。

比如 ods_es_pdi_product_full_1d 。

6 数据源是外部的(如excel):

表命名规则:odsoutside{自定义表名}{增全量}{调度频率} 。

比如 ods_outside_pdi_product_full_1d 。

4 数仓表命名规范:

1 分层域命名规范:

dwglobal/b2c/b2b/c2b/c2c . dw|dws{一级数据域}{二级数据域}{业务过程}XXXXX{增全量}_{跑数频率}

dimglobal/b2c/b2b/c2b/c2c . dim({一级数据域}{二级数据域})_XXXXX{增全量}_{跑数频率}

dmglobal/b2c/b2b/c2b/c2c . dm{数据主题域}XXXXX{增全量}_{跑数频率}

adsglobal/b2c/b2b/c2b/c2c/afs/media/core. ads{应用主题域}XXXXX{增全量}_{跑数频率}

tmpglobal/b2c/b2b/c2b/c2c . tmp目标表名oa账号[01...99]_yyyyMMdd

       临时表使用:按情况灵活考虑,建议优先使用with as语法(如果结果不占用太大内存情况下)代替临时表
临时表清理:任务中默认清理2天前创建临时表
临时表注意点:任务中使用临时表如果没有清理机制,发现一次,值班一次

***业务主题域 业务主题域划分规则(DW)’

***数据主题域 数据主题域划分规则(DM)’

***应用主题域 应用主题域划分规则(ADS)’

2 增全量更新方式命名规范:

增量:inc 全量:full …… 3 分区表调度频率命名规范:

秒、分钟:1s 小时(hour):1h 天(day):1d 周(week):1w 月(month):1m 季度(quarter):1q 年(year):1y ...... 注意:单张表的分区每日新增不宜超过200个,分区太多导致文件分布太细,对集群namenode压力过大

4 非分区表表名时间粒度后面加:统一为”_0p”

示例

分区表

增量&小时 更新 xxx_inc_1h dt=yyyy-MM-dd-HH

全量&小时 更新 xxx_full_1h dt=yyyy-MM-dd

增量&天 更新 xxx_inc_1d dt=yyyy-MM-dd

全量&天 更新 xxx_full_1d dt=yyyy-MM-dd

增量&周 更新 xxx_inc_1w dt=yyyy-MM-dd

全量&周 更新 xxx_full_1w dt=yyyy-MM-dd

5 分区字段

ods 、dw、dm、dim、ads 可视情况建分区表,分区字段统一为dt 。

ods 可视情况建分区表,非分区表无需保留dt字段。

dim不建议使用分区表,保留一份最新数据即可。

dw、dm建议使用分区表,不是分区表的,表中仍然需要保留dt字段,作用和分区字段dt同理,格式也同dt。

ads 是否使用分区表取决于每天的计算结果量, 每天跑批计算结果数据量千条以内的,ads不使用分区,其他可考虑分区。

ads 不管是不是分区 都需要加 stat_date ,作用和分区字段dt同理,格式也同dt。(主要是为了和回导mysql规范一致)

建表语句示例:

partitioned by (dt string comment '时间分区字段,形式yyyy-MM-dd')

partitioned by (dt string comment '时间分区字段,形式yyyy-MM-dd-HH')

partitioned by (dt string comment '时间分区字段,形式yyyy-MM')

partitioned by (dt string comment '时间分区字段,形式yyyy')

6 表注释规范

1、所有表(不区分hive表或ysql表)和字段的注释都必须使用comment语句增加注释,原则是简单明了且完整,能反映真实数据的。

2、字段单位注释规范,如:

金额举例 :销售额(元) 价格举例:回收价(分) 重量举例:包裹重量(kg) 时间举例:发货时长(毫秒)

7 字段默认值规范

数仓内部的字段要求全部清洗,清洗以后除有意义值以外,全部使用默认值。

度量数值类型默认值:0

其他数值类型默认值:-9

字符串类型字段默认值:''