数据集市(Data Market):是一种微型的数据仓库,它通常有更少的数据,更少的主题区域,以及更少的历史数据,因此是部门级的,一般只能为某个局部范围内的管理人员服务。
数据仓库(Data Warehouse):数据仓库是企业级的,能为整个企业各个部门的运行提供决策支持手段。
ODS(数据源层,原始数据) – ETL --> DWD(数据明细层) – hive sql --> DWS(数据汇总) – sqoop --> ADS(数据应用:报表、用户画像)
在阿里巴巴的数据体系中,建议将数据仓库分为三层,自下而上为:
数据引入层ODS(Operation Data Store):存放未经过处理的原始数据至数据仓库系统,结构上与源系统保持一致,是数据仓库的数据准备区。主要完成基础数据引入到MaxCompute的职责,同时记录基础数据的历史变化。
数据公共层CDM(Common Data Model,又称通用数据模型层):包括DIM维度表、DWD和DWS,由ODS层数据加工而成。主要完成数据加工与整合,建立一致性的维度,构建可复用的面向分析和统计的明细事实表,以及汇总公共粒度的指标,根据目前业务特点,暂时只建立DWD层
数据应用层ADS(Application Data Service):存放数据产品个性化的统计指标数据。根据CDM与ODS层加工生成。
中英文及简写:
数据引入层(ODS,Operation Data Store)
数据公共层(CDM,Common Data Model)
公共维度层(DIM,Dimension)
数仓明细层(DWD,Data Warehouse Detail)
数据汇总层(DWS,Data Warehouse Service)
数据应用层(ADS,Application Data Service)。
1) 数据引入层(ODS,Operation Data Store):将原始数据几乎无处理的存放在数据仓库系统,结构上与源系统基本保持一致,是数据仓库的数据准备区。原始数据,主要是埋点数据(日志数据)和业务操作数据(binlong),数据源主要是 Mysql、HDFS、Kafka 等
2) 数据公共层(CDM,Common Data Model,又称通用数据模型层),包括 DIM 维度表、DWD 和 DWS,由ODS 层数据加工而成。主要完成数据加工与整合,建立一致性的维度,构建可复用的面向分析和统计的明细事实表,以及汇总公共粒度的指标。这一层里又包括三层:
3) 数据应用层(ADS,Application Data Service):存放数据产品个性化的统计指标数据。根据 CDM 与 ODS 层加工生成。
1) ods 层
增量数据: {project_name}.ods_{数据来源}_{源系统表名}_delta
全量数据: {project_name}.ods_{数据来源}_{源系统表名}
数据来源说明:
01 -> hdfs 数据
02 -> mysql 数据
03 -> redis 数据
04 -> mongodb 数据
05 -> tidb 数据
举例如下:
行为日志表: ods_01_action_log
用户表: ods_02_user
2) dim 层
公共区域维表: {project_name}.dim_pub_{自定义命名标签}
具体业务维表: {project_name}.dim_{业务缩写}_{自定义命名标签}
举例如下:
公共区域维表: dim_pub_area
公共时间维表: dim_pub_date
A公司电商板块的商品全量表: dim_asale_itm
3) dwd 层
多个业务公共表: {project_name}.dwd_pub_{自定义命名标签}
具体业务数据增量表: {project_name}.dwd_{业务缩写}_{自定义命名标签}_di
具体业务数据全量表: {project_name}.dwd_{业务缩写}_{自定义命名标签}_df
举例如下:
交易会员信息事实表:ods_asale_trd_mbr_di
交易商品信息事实表:dwd_asale_trd_itm_di
交易订单信息事实表:dwd_asale_trd_ord_di
4) dws 层
多个业务公共表: {project_name}.dws_pub_{自定义命名标签}
具体业务最近一天汇总事实表: {project_name}.dws_{业务缩写}_{自定义命名标签}_1d
具体业务最近N天汇总事实表: {project_name}.dws_{业务缩写}_{自定义命名标签}_nd
具体业务历史截至当天汇总表: {project_name}.dws_{业务缩写}_{自定义命名标签}_td
具体业务小时汇总表: {project_name}.dws_{业务缩写}_{自定义命名标签}_hh
举例如下:
dws_asale_trd_byr_subpay_1d(A电商公司买家粒度交易分阶段付款一日汇总事实表)
dws_asale_trd_byr_subpay_td(A电商公司买家粒度分阶段付款截至当日汇总表)
dws_asale_trd_byr_cod_nd(A电商公司买家粒度货到付款交易汇总事实表)
dws_asale_itm_slr_td(A电商公司卖家粒度商品截至当日存量汇总表)
dws_asale_itm_slr_hh(A电商公司卖家粒度商品小时汇总表)---维度为小时
dws_asale_itm_slr_mm(A电商公司卖家粒度商品分钟汇总表)---维度为分钟
5) ads 层
{project_name}.ads_{业务缩写}_{自定义命名标签}
举例如下:
订单统计表: ads_nshop_order_form
订单支付统计: ads_nshop_orderpay_form
1) 业务数据
业务数据往往产生于事务型过程处理,所以一般存储在关系型数据库中,如 mysql、oracle。
业务数据源: 用户基本信息、商品分类信息、商品信息、店铺信息、订单数据、订单支付信息、活动信息、物流信息等
2) 埋点日志
埋点日志相对业务数据是用于数据分析、挖掘需求,一般以日志形式存储于日志文件中,随后通过采集落地分布式存储介质中如 hdfs、hbase。
用户行为日志: 用户浏览、用户点评、用户关注、用户搜索、用户投诉、用户咨询
3) 外部数据
当前一般公司都会通过线上广告来进行获客,与三方公司合作更多的提取相关数据来进行深度刻画用户及用户群体,另外爬取公共公开数据也是分析运营的常用方式。
外部数据源: 广告投放数据、爬虫数据、三方接口数据
数仓层内部的划分不是为了分层而分层,分层是为了解决 ETL 任务及工作流的组织、数据的流向、读写权限的控制、不同需求的满足等各类问题。
业界较为通行的做法将整个数仓层(DW)又划分成了 dwd、dwb、dws、dim、mid 等等很多层。然而我们却始终说不清楚这几层之间清晰的界限是什么,或者说我们能说清楚它们之间的界限,复杂的业务场景却令我们无法真正落地执行。
所以数据分层这块一般来说 ODS、DWD、DWS 这三层是最基础的:
至于DW层如何进行切分,是根据具体的业务需求和公司场景自己去定义,一般来说需要:
DW 内的分层没有最正确的,只有最适合你的。
在数仓层开始引入了宽表。所谓宽表,迄今为止并没有一个明确的定义。通常做法是把很多的维度、事实上卷(roll-up)或者下钻(drill-down)之后关联到某一个事实表中,形成一张既包含了大量维度又包含了相关事实的表。
宽表的使用,有其一定的便利性。使用方不需要再去考虑跟维度表的关联,也不需要了解维度表和事实表是什么东西。
但是随着业务的增长,我们始终无法预见性地设计和定义宽表究竟该冗余多少维度,也无法清晰地定义出宽表冗余维度的底线在哪里。
一个可能存在的情况是,为了满足使用上的需求,要不断地将维表中已经存在的列增加到宽表中。这直接导致了宽表的表结构频繁发生变动。
目前我们所采用的做法是:
为什么说尽量用维度建模代替宽表,就算字段和数据会冗余,维度建模的方式也会表全量数据的宽表模式较好,原因:
1)定义
范式可以理解为设计一张数据表的表结构,符合的标准级别、规范和要求。
2)优点
采用范式,可以降低数据的冗余性。
为什么要降低数据冗余性?
(1)十几年前,磁盘很贵,为了减少磁盘存储。
(2)以前没有分布式系统,都是单机,只能增加磁盘,磁盘个数也是有限的
(3)一次修改,需要修改多个表,很难保证数据一致性
3)缺点
范式的缺点是获取数据时,需要通过Join拼接出最后的数据。
4)分类
目前业界范式有:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF)。
1、完全函数依赖
设X、Y是关系R的两个属性集合,X'是X的真子集,存在X→Y,但对于每一个X'都有X'!→Y,则称Y完全函数依赖于X。
比如通过,(学号,课程)推出分数,那么就可以说:分数完全依赖于(学号,课程)。
即:通过AB能得出C,但是AB单独得不出C,那么说C完全依赖于AB。
2、部分函数依赖
假如Y函数依赖于X,但同时Y并不完全函数依赖于X,那么我们就称Y部分函数依赖于X。
比如通过(学号,课程)推出姓名,因为直接可以通过学号推出姓名。所以姓名部分依赖于(学号,课程)
即:通过AB能得出C,通过A也能得出C,或者通过B也能得出C,那么说C部分依赖于AB。
3、传递函数依赖
设X、Y、Z是关系R中互不相同的属性集合,存在X→Y(Y'!→X),Y→Z,则称Z传递函数依赖于X。
学号推出系名,系名推出系主任,但是系主任推不出学号,系主任主要依赖于系名。这种情况可以说系主任传递依赖于学号。
即:通过A得到B,通过B得到C,但是C得不到A,那么说C传递依赖于A。
第一范式
1NF核心原则:属性不可切割
很明显上图所示的表格设计是不符合第一范式的,商品列中的数据不是原子数据项,是可以进行分割的,于是对表格进行修改,让表格符合第一范式的要求,如下图所示:
事实上,1NF是所有关系型数据库的最基本要求,只要在RDBMS中已经存在的数据表,一定是符合1NF的。
第二范式
2NF核心原则:不能存在部分函数依赖
以上表格明显存在部分依赖。比如,这张表的主键是(学号,课名),分数确实完全依赖于(学号,课名),但是姓名并不完全依赖于(学号,课名)。
上图右面表格符合第二范式,去掉了部分函数依赖。
第三范式
3NF核心原则:不能存在传递函数依赖
在下图所示表格中,存在传递函数依赖:学号->系名->系主任,但是系主任推不出学号。
当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。二者的主要区别对比如下表所示。
对比属性 |
OLTP |
OLAP |
读特性 |
每次查询只返回少量记录 |
对大量记录进行汇总 |
写特性 |
随机、低延时写入用户的输入 |
批量导入 |
使用场景 |
用户,Java EE项目 |
内部分析师,为决策提供支持 |
数据表征 |
最新数据状态 |
随时间变化的历史状态 |
数据规模 |
GB |
TB到PB |
关系模型如图所示,严格遵循第三范式(3NF),从图中可以看出,较为松散、零碎,物理表数量多,而数据冗余程度低。由于数据分布于众多的表中,这些数据可以更为灵活地被应用,功能性较强。关系模型主要应用与OLTP系统中,为了保证数据的一致性以及避免冗余,所以大部分业务系统的表都是遵循第三范式的。
维度模型如图所示,主要应用于OLAP系统中,通常以某一个事实表为中心进行表的组织,主要面向业务,特征是可能存在数据的冗余,但是能方便的得到数据。
关系模型虽然冗余少,但是在大规模数据,跨表分析统计查询过程中,会造成多表关联,这会大大降低执行效率。所以通常我们采用维度模型建模,把相关各种表整理成两种:事实表和维度表两种。
维度表:一般是对事实的描述信息。每一张维表对应现实世界中的一个对象或者概念。例如:用户、商品、日期、地区等。
在维度表中,每个表都包含独立于其他维度表的事实特性,例如,客户维度表包含有关客户的数据。维度表中的列字段可以将信息分为不同层次的结构级。
维表的特征:
时间维度表:
日期ID |
day of week |
day of year |
季度 |
节假日 |
2020-01-01 |
2 |
1 |
1 |
元旦 |
2020-01-02 |
3 |
2 |
1 |
无 |
2020-01-03 |
4 |
3 |
1 |
无 |
2020-01-04 |
5 |
4 |
1 |
无 |
2020-01-05 |
6 |
5 |
1 |
无 |
事实表:每个数据仓库都包含一个或者多个事实数据表。事实数据表可能包含业务销售数据,如现金登记事务所产生的数据,事实数据表通常包含大量的行。事实数据表的主要特点是包含数字数据(事实),并且这些数字信息可以汇总,以提供有关单位作为历史的数据,每个事实数据表包含一个由多个部分组成的索引,该索引包含作为外键的相关性纬度表的主键,而维度表包含事实记录的特性。事实数据表不应该包含描述性的信息,也不应该包含除数字度量字段及使事实与纬度表中对应项的相关索引字段之外的任何数据。
包含在事实数据表中的“度量值”有两中:一种是可以累计的度量值,另一种是非累计的度量值。最有用的度量值是可累计的度量值,其累计起来的数字是非常有意义的。用户可以通过累计度量值获得汇总信息,例如。可以汇总具体时间段内一组商店的特定商品的销售情况。非累计的度量值也可以用于事实数据表,单汇总结果一般是没有意义的,例如,在一座大厦的不同位置测量温度时,如果将大厦中所有不同位置的温度累加是没有意义的,但是求平均值是有意义的。
一般来说,一个事实数据表都要和一个或多个纬度表相关联,用户在利用事实数据表创建多维数据集时,可以使用一个或多个维度表。
事实表中的每行数据代表一个业务事件(下单、支付、退款、评价等)。“事实”这个术语表示的是业务事件的度量值(可统计次数、个数、金额等),例如,2020年5月21日,宋老师在京东花了250块钱买了一双安踏鞋。维度表:时间、用户、商品、商家。事实表:250块钱、一双
每一个事实表的行包括:具有可加性的数值型的度量值、与维表相连接的外键,通常具有两个和两个以上的外键。
事实表的特征:
1)事务型事实表
以每个事务或事件为单位,例如一个销售订单记录,一笔支付记录等,作为事实表里的一行数据。一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新。
2)周期型快照事实表
周期型快照事实表中不会保留所有数据,只保留固定时间间隔的数据,例如每天或者每月的销售额,或每月的账户余额等。
例如购物车,有加减商品,随时都有可能变化,但是我们更关心每天结束时这里面有多少商品,方便我们后期统计分析。
3)累积型快照事实表
累计快照事实表用于跟踪业务事实的变化。例如,数据仓库中可能需要累积或者存储订单从下订单开始,到订单商品被打包、运输、和签收的各个业务阶段的时间点数据来跟踪订单声明周期的进展情况。当这个业务过程进行时,事实表的记录也要不断更新。
订单id |
用户id |
下单时间 |
打包时间 |
发货时间 |
签收时间 |
订单金额 |
3-8 |
3-8 |
3-9 |
3-10 |
在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型。
星型模型和雪花模型的主要区别在于维度的层级,标准的星型模型维度只有一层,而雪花模型会涉及多级。
雪花模型,比较靠近3NF,但是无法完全遵守,因为遵循3NF的性能成本太高。
星座模型与前两种的区别是事实表的数量,星座模型是基于多个事实表。
基本上是很多数据仓库的常态,因为很多数据仓库都是多个事实表的,所以星座不星座只反映是否有多个事实表,他们之间是否共享一些维度表。所以星座模型并不和前两种冲突。
首先就是星座不星座这个只跟数据和需求有关系,跟设计没关系,不用选择。
星型还是雪花,取决于性能优化,还是灵活更优先。
目前实际企业开发中,不会绝对选择一种,根据情况灵活组合,甚至并存(一层维度和多层维度都保存)。但是整体来看,更倾向于维度更少的星型模型。尤其是Hadoop体系,减少Join就是减少Shuffle,性能差距很大。(关系型数据可以依靠强大的主键索引)