数据仓库设计与开发-1-分层设计

分层设计

  • 为什么要分层
  • 如何分层
    • 理论
    • 技术实践
  • 举个例子
  • 如何更优雅一些
  • 问答
  • 总结
  • 其他参考
  • ODS层的数据需要做数据清洗吗
  • 一种通用的数据仓库分层方法

转载 https://www.cnblogs.com/wang3680/p/11538451.html
转载 https://blog.csdn.net/zhaodedong/article/details/85293955

为什么要分层

对数据进行分层的一个主要原因对数据有更加清晰的掌控,主要有以下原因:

  • 清晰数据结构:每一个数据分层都有它的作用域,这样在使用表的时候能更方便地定位和理解。
  • 减少重复开发:规范数据分层,开发一些通用的中间层数据,能够减少极大的重复计算。
  • 统一数据口径:通过数据分层,提供统一的数据出口,统一对外输出的数据口径
  • 复杂问题简单化。讲一个复杂的任务分解成多个步骤来完成,每一层只处理单一的步骤,比较简单和容易理解。而且便于维护数据的准确性,当数据出现问题之后,可以不用修复所有的数据,只需要从有问题的步骤开始修复。
  • 数据血缘追踪:我们最终给业务诚信的是一能直接使用的张业务表,但是它的来源有很多,如果有一张来源表出问题了,我们希望能够快速准确地定位到问题,并清楚它的危害范围。
  • 屏蔽原始数据的异常。
  • 屏蔽业务的影响,不必改一次业务就需要重新接入数据。

数据体系中的各个表的依赖就像是电线的流向一样,我们都希望它是规整、流向清晰、便于管理的,如下图:
数据仓库设计与开发-1-分层设计_第1张图片
但是,最终的结果大多却是依赖复杂、层级混乱,想梳理清楚一张表的声称途径会比较困难,如下图:
数据仓库设计与开发-1-分层设计_第2张图片
作为一名数据的规划者,我们肯定希望自己的数据能够有秩序地流转,数据的整个生命周期能够清晰明确被设计者和使用者感知到。直观来讲就是如下的左图这般层次清晰、依赖关系直观。

但是,大多数情况下,我们完成的数据体系却是依赖复杂、层级混乱的。如下的右图,在不知不觉的情况下,我们可能会做出一套表依赖结构混乱,甚至出现循环依赖的数据体系。
数据仓库设计与开发-1-分层设计_第3张图片

如何分层

理论

数据仓库设计与开发-1-分层设计_第4张图片

  • 技术缓冲层
  • ODS 全称是 Operational Data Store,它是“面向主题的”,最接近数据源中数据的一层。数据源中的数据,经过抽取、洗净、传输,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。但是,这一层面的数据却不等同于原始数据。【在源数据装入这一层时,要进行诸如去噪(例如有一条数据中人的年龄是 300 岁,这种属于异常数据,就需要提前做一些处理)、去重(例如在个人资料表中,同一 ID 却有两条重复数据,在接入的时候需要做一步去重)、字段命名规范等一系列操作。】 ODS 层提供面向主题的、数据质量可靠的、明细数据层。
  • 数据仓库层(DW),是数据仓库的主体.在这里,从 ODS 层中获得的数据按照主题建立各种数据模型。这一层和维度建模会有比较深的联系,可以多参考一下前面的几篇文章。
  • 数据应用层层(APP),这一层是提供为数据产品使用的结果数据。在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在 ES、Mysql 等系统中供线上系统使用,也可能会存在 Hive 或者 Druid 中供数据分析和数据挖掘使用。如我们经常说的报表数据,或者说那种大宽表,一般就放在这里。

技术实践

这三层技术划分,相对来说比较粗粒度,后面我们会专门细分一下。在此之前,先聊一下每一层的数据一般都是怎么流向的。这里仅仅简单介绍几个常用的工具,侧重中开源界主流。

  1. 数据来源层→ ODS层
    这里其实就是我们现在大数据技术发挥作用的一个主要战场。 我们的数据主要会有两个大的来源:
  • 业务库,这里经常会使用 Sqoop 来抽取,比如我们每天定时抽取一次。在实时方面,可以考虑用 Canal 监听 Mysql 的 Binlog,实时接入即可。
  • 埋点日志,线上系统会打入各种日志,这些日志一般以文件的形式保存,我们可以选择用 Flume 定时抽取,也可以用用 Spark Streaming 或者 Storm 来实时接入,当然,Kafka 也会是一个关键的角色。
  • 其它数据源会比较多样性,这和具体的业务相关,不再赘述。
    数据仓库设计与开发-1-分层设计_第5张图片
    注意: 在这层,理应不是简单的数据接入,而是要考虑一定的数据清洗,比如异常字段的处理、字段命名规范化、时间字段的统一等,一般这些很容易会被忽略,但是却至关重要。特别是后期我们做各种特征自动生成的时候,会十分有用。后续会有文章来分享。
  1. ODS、DW → App层
    这里面也主要分两种类型:
  • 每日定时任务型:比如我们典型的日计算任务,每天凌晨算前一天的数据,早上起来看报表。 这种任务经常使用 Hive、Spark 或者生撸 MR 程序来计算,最终结果写入 Hive、Hbase、Mysql、Es 或者 Redis 中。
  • 实时数据:这部分主要是各种实时的系统使用,比如我们的实时推荐、实时用户画像,一般我们会用 Spark Streaming、Storm 或者 Flink 来计算,最后会落入 Es、Hbase 或者 Redis 中。

举个例子

网上的例子很多,就不列了,只举个笔者早期参与设计的数据分层例子。分析一下当初的想法,以及这种设计的缺陷。上原图和内容。当初的设计总共分了 6 层,其中去掉元数据后,还有5层。下面分析一下当初的一个设计思路

数据仓库设计与开发-1-分层设计_第6张图片

  1. 缓冲层(buffer)
  • 概念:又称为接口层(stage),用于存储每天的增量数据和变更数据,如Canal接收的业务变更日志。
  • 数据生成方式:直接从kafka接收源数据,需要业务表每天生成update, delete, inseret数据,只生成insert数据的业务表,数据直接入明细层
  • 讨论方案:只把canal日志直接入缓冲层,如果其它有拉链数据的业务,也入缓冲层。
  • 日志存储方式:使用impala外表,parquet文件格式,方便需要MR处理的数据读取。
  • 日志删除方式:长久存储,可只存储最近几天的数据。讨论方案:直接长久存储
  • 表schema:一般按天创建分区
  • 库与表命名。库名:buffer,表名:初步考虑格式为:buffer日期业务表名,待定。
  1. 明细层(ODS, Operational Data Store,DWD: data warehouse detail)
  • 概念:是数据仓库的细节数据层,是对STAGE层数据进行沉淀,减少了抽取的复杂性,同时ODS/DWD的信息模型组织主要遵循企业业务事务处理的形式,将各个专业数据进行集中,明细层跟stage层的粒度一致,属于分析的公共资源
  • 数据生成方式:部分数据直接来自kafka,部分数据为接口层数据与历史数据合成。

canal日志合成数据的方式待研究。

  • 讨论方案:canal数据的合成方式为:每天把明细层的前天全量数据和昨天新数据合成一个新的数据表,覆盖旧表。同时使用历史镜像,按周/按月/按年 存储一个历史镜像到新表。
  • 日志存储方式:直接数据使用impala外表,parquet文件格式,canal合成数据为二次生成数据,建议使用内表,下面几层都是从impala生成的数据,建议都用内表+静态/动态分区。
  • 日志删除方式:长久存储。
  • 表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
  • 库与表命名。库名:ods,表名:初步考虑格式为ods日期业务表名,待定。
  • 旧数据更新方式:直接覆盖
  1. 轻度汇总层(MID或DWB, data warehouse basis)
  • 概念:轻度汇总层数据仓库中DWD层和DM层之间的一个过渡层次,是对DWD层的生产数据进行轻度综合和汇总统计(可以把复杂的清洗,处理包含,如根据PV日志生成的会话数据)。
    DWD与轻度汇总层(DWB)与的主要区别在于二者的应用领域不同,DWD的数据来源于生产型系统,并未满意一些不可预见的需求而进行沉淀;轻度综合层则面向分析型应用进行细粒度的统计和沉淀
  • 数据生成方式:由明细层按照一定的业务需求生成轻度汇总表。明细层需要复杂清洗的数据和需要MR处理的数据也经过处理后接入到轻度汇总层。
  • 日志存储方式:内表,parquet文件格式。
  • 日志删除方式:长久存储。
  • 表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
  • 库与表命名。库名:dwb,表名:初步考虑格式为:dwb日期业务表名,待定。
  • 旧数据更新方式:直接覆盖
  1. 主题层(DM,data market或DWS, data warehouse service)
  • 概念:又称数据集市或宽表。按照业务划分,如流量、订单、用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据分发等。
  • 数据生成方式:由轻度汇总层和明细层数据计算生成。
  • 日志存储方式:使用impala内表,parquet文件格式。
  • 日志删除方式:长久存储。
  • 表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
  • 库与表命名。库名:dm,表名:初步考虑格式为:dm日期业务表名,待定。
  • 旧数据更新方式:直接覆盖
  1. 应用层(App)
  • 概念:应用层是根据业务需要,由前面三层数据统计而出的结果,可以直接提供查询展现,或导入至Mysql中使用。
  • 数据生成方式:由明细层、轻度汇总层,数据集市层生成,一般要求数据主要来源于集市层。
  • 日志存储方式:使用impala内表,parquet文件格式。
  • 日志删除方式:长久存储。
  • 表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
  • 库与表命名。库名:暂定apl,另外根据业务不同,不限定一定要一个库。
  • 旧数据更新方式:直接覆盖。

如何更优雅一些

前面提到的一种设计其实相对来讲已经很详细了,但是可能层次会有一点多,而且在区分一张表到底该存放在什么位置的时候可能还有不小的疑惑。我们在这一章里再设计一套数据仓库的分层,同时在前面的基础上加上维表和一些临时表的考虑,来让我们的方案更优雅一些。

下图,做了一些小的改动,

  • 去掉了上一节的Buffer层
  • 把数据集市层和轻度汇总层放在同一个层级上
  • 独立出来了维表和临时表
    数据仓库设计与开发-1-分层设计_第7张图片
    这里解释一下DWS、DWD、DIM和TMP的作用。
  • DWD:这一层主要解决一些数据质量问题和数据的完整度问题。比如用户的资料信息来自于很多不同表,而且经常出现延迟丢数据等问题,为了方便各个使用方更好的使用数据,我们可以在这一层做一个屏蔽。
  • DWS:轻度汇总层,从ODS层中对用户的行为做一个初步的汇总,抽象出来一些通用的维度:时间、ip、id,并根据这些维度做一些统计值,比如用户每个时间段在不同登录ip购买的商品数等。这里做一层轻度的汇总会让计算更加的高效,在此基础上如果计算仅7天、30天、90天的行为的话会快很多。我们希望80%的业务都能通过我们的DWS层计算,而不是ODS。
  • DIM:这一层比较单纯,举个例子就明白,比如国家代码和国家名、地理位置、中文名、国旗图片等信息就存在DIM层中。
  • TMP:每一层的计算都会有很多临时表,专设一个DWTMP层来存储我们数据仓库的临时表。

问答

  • 问答一: 关于 ods, dwd, dws 的关系
    问:dws 和dwd 是并行而不是先后顺序?
    答:并行的,dw 层
    问:那其实对于同一个数据,这两个过程是串行的?
    答:dws 会做汇总,dwd 和 ods 的粒度相同,这两层之间也没有依赖的关系
    问:对呀,那这样 dws 里面的汇总没有经过数据质量和完整度的处理,或者单独做了这种质量相关的处理,为什么不在 dwd 之上再做汇总呢?我的疑问其实就是,dws的轻度汇总数据结果,有没有做数据质量的处理?
    答:ods 直接到 dws 就好,没必要过 dwd,我举个例子,你的浏览商品行为,我做一层轻度汇总,就直接放在 dws 了。但是你的资料表,要从好多表凑成一份,我们从四五份个人资料表中凑出来了一份完整的资料表放在了 dwd 中。然后在 app 层,我们要出一张画像表,包含用户资料和用户近一年的行为,我们就直接从dwd中拿资料, 然后再在 dws 的基础上做一层统计,就成一个app表了。当然,这不是绝对,dws 和 dwd 有没有依赖关系主要看有没有这种需求。

  • 问答二: ods 和 dwd 的区别
    问:还是不太明白 ods 和 dwd 层的区别,有了 ods 层后感觉 dwd 没有什么用了。
    答:嗯,我是这样理解的,站在一个理想的角度来讲,如果 ods 层的数据就非常规整,基本能满足我们绝大部分的需求,这当然是好的,这时候 dwd 层其实也没太大必要。 但是现实中接触的情况是 ods 层的数据很难保证质量,毕竟数据的来源多种多样,推送方也会有自己的推送逻辑,在这种情况下,我们就需要通过额外的一层 dwd 来屏蔽一些底层的差异。
    问:我大概明白了,是不是说 dwd 主要是对 ods 层做一些数据清洗和规范化的操作,dws 主要是对 ods 层数据做一些轻度的汇总?
    答:对的,可以大致这样理解。

问答三:app 层是干什么的?
问:感觉数据集市层是不是没地方放了,各个业务的数据集市表是应该在 dwd 还是在 app?
答:这个问题不太好回答,我感觉主要就是明确一下数据集市层是干什么的,如果你的数据集市层放的就是一些可以供业务方使用的宽表表,放在 app 层就行。如果你说的数据集市层是一个比较泛一点的概念,那么其实 dws、dwd、app 这些合起来都算是数据集市的内容。
问:那存到 Redis、ES 中的数据算是 app层吗?
答:算是的,我个人的理解,app 层主要存放一些相对成熟的表,能供业务侧使用的。这些表可以在 Hive 中,也可以是从 Hive 导入 Redis 或者 ES 这种查询性能比较好的系统中。

个人认为 应当遵循以下顺序
ods[与源端保持一致的明细数据]->
dwd[经过数据质量检查的明细数据]->
dws[轻度汇总]

总结

数据分层是数据仓库非常重要的一个环节,它决定的不仅仅是一个层次的问题,还直接影响到血缘分析、特征自动生成、元数据管理等一系列功能的建设。因此适于尽早考虑。

其他参考

数据仓库设计与开发-1-分层设计_第8张图片

  • ODS层
    ODS层中的数据全部来自于业务数据库,ODS层的表格也业务数据库中的表格一一对应,就是将业务数据库中的表格在数据仓库的底层重新建立一次,数据与结构完全一致。
    由于业务数据库(OLTP)基本按照ER实体模型建模,因此ODS层中的建模方式也是ER实体模型。

  • DW层
    DWD层要做的就是将数据清理、整合、规范化、脏数据、垃圾数据、规范不一致的、状态定义不一致的、命名不规范的数据都会被处理。DWD层应该是覆盖所有系统的、完整的、干净的、具有一致性的数据层。在DWD层会根据维度模型,设计事实表和维度表,也就是说DWD层是一个非常规范的、高质量的、可信的数据明细层。

DWS层为公共汇总层,会进行轻度汇总,粒度比明细数据稍粗,基于DWD层上的基础数据,整合汇总成分析某一个主题域的服务数据,一般是宽表。DWS层应覆盖80%的应用场景。

  • DM层
    DM层为数据集市层,面向特定主题。在DM层完成报表或者指标的统计,DM层已经不包含明细数据,是粗粒度的汇总数据。DM层是针对某一个业务领域建立模型,具体用户(一般为决策层)查看DM层生成的报表。

ODS层的数据需要做数据清洗吗

问题: ODS 有的公司说几乎不处理,有的说这一层要做第一次数据清洗,大家怎么看?

  • 讨论一: 我感觉基本的监控要做,然后字段类型,命名统一可以做,ip转地址也可以做。复杂的 不太容易做,数据源的接入不一定都可控。
  • 讨论二: 看数据的规整性吧。有的公司业务方数据很规整。ODS层只用做简单的砍字段即可,有的业务数据不规整比如埋点类的那么不做清洗就肯定不行了。有公司是从业务库直接到ODS,那么需要做备份, 有的是从业务库到汇总库再到ODS。那么汇总库就可以看作是备份了。
  • 讨论三: 个人觉得ODS层的数据还是需要清洗并存入到数据仓库比较合适。如果不清洗,是ETL任务的计算资源和计算时间的浪费。除非是有特殊需要,规定要原汁原味的“原始数据”。

这个问题,从本质上来看,其实是和分层的设计以及公司的业务场景相关的。
先抛开公司的业务场景来看ODS的设计,我们其实是希望ODS的数据尽量“原汁原味”,但又相对干净。那么,这个尺度或者说标准怎么来把握?简单来看,我们会让ODS层的数据内容和粒度与原始数据一致,然后我们会做表命名统一、字段命名统一、数据落地监控等内容。

然后对于数据清洗,居士个人建议是尽量少做清洗,如果在这一层做清洗,建议只在几种情况下做清洗:

  • 简单的数据标准化,比如表和字段命名
  • 默认值填充,比如性别为空的都补0
  • 清洗规则十分明确,比如说说字段拆解:
  • 接收到的json数据拆成多个明确字段

其余情况下不是不能做清洗,而是说尽量少做清洗,因为一旦对原始数据稍作破坏,以后追查数据的成本会十分巨大。

当我们明确ODS的职责后,再来看不同公司的ODS设计。如果说数据源很干净,那么直接拿来就可以,基本不用处理。如果说数据源很混乱,而且清洗的规则十分明确,不会出现返工的情况,那么就可以在入ODS之前做一部分的清洗。

一种通用的数据仓库分层方法

为了满足前面提到数据分层带来的好处,我们将数据模型分为三层:数据运营层( ODS )、数据仓库层(DW)和数据应用层(APP)

  • ODS层存放的是接入的原始数据
  • DW层是存放我们要重点设计的数据仓库中间层数据
  • APP是面向业务定制的应用数据
    数据仓库设计与开发-1-分层设计_第9张图片
  1. 数据运营层:ODS(Operational Data Store)
    “面向主题的”,数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的 ETL 之后,装入本层。本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。
    一般来讲,为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可,至于数据的去噪、去重、异常值处理等过程可以放在后面的DWD层来做。

  2. 数据仓库层:DW(Data Warehouse)
    数据仓库层是我们在做数据仓库时要核心设计的一层,在这里,从 ODS 层中获得的数据按照主题建立各种数据模型。DW层又细分为 DWD(Data Warehouse Detail)层、DWB(Data WareHouse Basic)层和DWS(Data WareHouse Servce)层。

  • 数据明细层:DWD(Data Warehouse Detail)
    该层一般保持和ODS层一样的数据粒度,并且提供一定的数据质量保证。同时,为了提高数据明细层的易用性,该层会采用一些维度退化手法,将维度退化至事实表中,减少事实表和维表的关联。
  • 数据中间层:DWM(Data WareHouse Basic)
    该层会在DWD层的数据基础上,对数据做轻度的聚合操作,生成一系列的中间表,提升公共指标的复用性,减少重复加工。直观来讲,就是对通用的核心维度进行聚合操作,算出相应的统计指标。
  • 数据服务层:DWS(Data WareHouse Servce)
    又称数据集市或宽表。按照业务划分,如流量、订单、用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据分发等。
    一般来讲,该层的数据表会相对比较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。
  1. 数据应用层:APP(Application)
    在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在 ES、PostgreSql、Redis等系统中供线上系统使用,也可能会存在 Hive 或者 Druid 中供数据分析和数据挖掘使用。比如我们经常说的报表数据,一般就放在这里。

  2. 维表层(Dimension)
    最后补充一个维表层,维表层主要包含两部分数据:

  • 高基数维度数据:一般是用户资料表、商品资料表类似的资料表。数据量可能是千万级或者上亿级别。
  • 低基数维度数据:一般是配置表,比如枚举值对应的中文含义,或者日期维表。数据量可能是个位数或者几千几万。
    数据仓库设计与开发-1-分层设计_第10张图片
    举个栗子
    趁热打铁,举个栗子说明一下,如下图,可以认为是一个电商网站的数据体系设计。我们暂且只关注用户访问日志这一部分数据。
  • 在ODS层中,由于各端的开发团队不同或者各种其它问题,用户的访问日志被分成了好几张表上报到了我们的ODS层。
  • 为了方便大家的使用,我们在DWD层做了一张用户访问行为天表,在这里,我们将PC网页、H5、小程序和原生APP访问日志汇聚到一张表里面,统一字段名,提升数据质量,这样就有了一张可供大家方便使用的明细表了。
  • 在DWM层,我们会从DWD层中选取业务关注的核心维度来做聚合操作,比如只保留人、商品、设备和页面区域维度。类似的,我们这样做了很多个DWM的中间表
  • 然后在DWS层,我们将一个人在整个网站中的行为数据放到一张表中,这就是我们的宽表了,有了这张表,就可以快速满足大部分的通用型业务需求了。
  • 最后,在APP应用层,根据需求从DWS层的一张或者多张表取出数据拼接成一张应用表即可。

备注:例子只是为了简单地说明每一层的作用,并不是最合理的解决方案,大家辩证地看待即可。
数据仓库设计与开发-1-分层设计_第11张图片
既然谈到了数据分层,那不同的层次中会用到什么计算引擎和存储系统呢,本节来简单分享一下。

数据层的存储一般如下:

  • Data Source:数据源一般是业务库和埋点,当然也会有第三方购买数据等多种数据来源方式。业务库的存储一般是Mysql 和 PostgreSql。
  • ODS 层:ODS 的数据量一般非常大,所以大多数公司会选择存在HDFS上,即Hive或者Hbase,Hive居多。
  • DW 层:一般和 ODS 的存储一致,但是为了满足更多的需求,也会有存放在 PG 和 ES 中的情况。
  • APP 层:应用层的数据,一般都要求比较快的响应速度,因此一般是放在 Mysql、PG、Redis中。

计算引擎的话,可以简单参考图中所列就行。目前大数据相关的技术更新迭代比较快,本节所列仅为简单参考。
数据仓库设计与开发-1-分层设计_第12张图片
如同《漫谈数据仓库和范式》一文在最后思考数据仓库和范式之间的关系一样,本文也将思考和总结一下数据分层的原则是什么?为什么要这样分层?每层之间的界限又是什么?

我个人从这几个角度来理解数据分层的划分:

从对应用的支持来讲,我们希望越靠上层次,越对应用友好。比如APP层,基本是完全为应用来设计的,很易懂,DWS层的话,相对来讲就会有一点点理解成本,然后DWM和DWD层就比较难理解了,因为它的维度可能会比较多,而且一个需求可能要多张表经过很复杂的计算才能完成。

从能力范围来讲,我们希望80%需求由20%的表来支持。直接点讲,就是大部分(80%以上)的需求,都用DWS的表来支持就行,DWS支持不了的,就用DWM和DWD的表来支持,这些都支持不了的极少一部分数据需要从原始日志中捞取。结合第一点来讲的话就是:80%的需求,我们都希望以对应用很友好的方式来支持,而不是直接暴露给应用方原始日志。

从数据聚合程度来讲,我们希望,越上层数据的聚合程度越高,看上面的例子即可,ODS和DWD的数据基本是原始日志的粒度,不做任何聚合操作,DWM做了轻度的聚合操作只保留了通用的维度,DWS做了更高的聚合操作,可能只保留一到两个能表征当前描述主体的维度。从这个角度来看,我们又可以理解为我们是按照数据的聚合程度来划分数据层次的。

你可能感兴趣的:(数据仓库设计与开发,数据仓库)