一、数仓分层
1.1 数仓分层
ODS
(Operation Data Store):原始数据层,关系建模,存放原始数据,直接加载原始日志、数据,数据保持原貌不做处理
DWD
(Data Warehouse Detail):明细数据层,维度建模,对ODS层数据进行清洗(去除空值,脏数据,超过极限范围的数据)、维度退化、脱敏等
DWS
(Data Warehouse Service):服务数据层,以DWD为基础,实际的工作中,需要算某个app,过去1天/周/月/季度/年,上线以来的新增用户…
DWT
(Data Warehouse Topic):数据主题层,以DWS为基础,按主题建模,主题使一个分析问题的角度,圈定了一个分析的范围,计算出这个主题各种指标,而我们的指标主要都是汇总,在DWS里面我们只汇总了过去1天的数据,得到1天作为粒度的指标…
ADS
(Application Data Store):数据应用层,给产品经理需要各种统计结果,直接从DWS和DWT很快的得到
1.2 为什么分层
-
把复杂问题简单化
将复杂的任务分解成多层来完成,每一层只处理简单的任务,方便定位问题
-
减少重复开发
规范数据分层,通过的中间层数据,能够减少极大的重复计算,增加一次计算结果的复用性
-
隔离原始数据
不论是数据的异常还是数据的敏感性,使真实数据与统计数据解耦开
1.3 数据集市与数据仓库概念
数据集市(Data Market)是一种微型的数据仓库,它通常有更少的数据,更少的主题区域,以及更少的历史数据,因此是部门级的,一般只能为某个局部范围内的管理人员服务
数据仓库是企业级的,能为整个企业各个部门的运行提供决策支持手段
1.4 数仓命名规范
1.4.1 表命名
- ODS层命名为ods_表名
- DWD层命名为dwd_dim/fact_表名(dim:维度表,fact:事实表)
- DWS层命名为dws_表名
- DWT层命名为dwt_表名
- ADS层命名为ads_表名
- 临时表命名为xxx_tmp,为了得到一些结果临时数据,随时的删除,一般建的是内部表
- 用户行为表,以log为后缀,如果不加就是db
1.4.2 脚本命名
-
驼峰命名法:UserInfoActivity
-
蛇形命名法:user_info_acti
数据源_to_目标_db/log.sh,命名风格是蛇形风格,单词之间都是小写,单词1_单词2…
用户行为脚本以log为后缀
业务数据脚本以db为后缀
二、数仓理论
2.1 范式理念
2.1.1 范式概念
-
定义
范式可以理解为设计一张数据表的表结构,符合的标准级别
-
优点
降低数据的冗余性,保证数据一致性,方便增删
问题:为什么要降低数据冗余性?
1.十几年前,磁盘很贵,为了减少磁盘存储 2.以前没有分布式系统,都是单机,只能增加磁盘,磁盘个数也是有限的 3.一次修改,需要修改多个表,很难保证数据一致性 4.方便增删数据
-
缺点
获取数据时,需要通过join拼接出最后的数据
因为这个业务数据主要是对单条或者多条数据的随机读写,这样join成本就不会那么高;但是大数据里面是把过去1天/周/月…所有的数据来处理,如果还有大量的join就会导致处理速度非常的慢
-
分类
目前业界范式有:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)、第五范式(5NF)
2.1.2 函数依赖
-
完全函数依赖
通过AB能得出C,但是AB单独得不出C,那么说C完全依赖于AB
-
部分函数依赖
通过AB能得出C,通过A也能得出C,或者通过B也能得出C,那么说C部分依赖于AB
-
传递函数依赖
通过A得到B,通过B得到C,但是C得不到A,那么说C传递依赖于A
2.1.3 三范式区分
-
第一范式核心原理:属性不可切割
1NF是所有关系型数据库的最基本要求,你在关系型数据库管理系统(RDBMS),例如SQL Server,Oracle,MySQL中创建数据表的时候,如果数据表的设计不符合这个最基本的要求,那么操作一定是不能成功的,也就是说,只要RDBMS中已经存在的数据表,一定是符合1NF的
-
第二范式核心原理:不能存在“部分函数依赖”
-
第三范式核心原理:不能存在传递函数依赖
2.2 关系建模与维度建模(重中之重)
当今的数据处理大致可以分为两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(on-line analytical processing)
OLTP
:是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易
OLAP
:是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果
二者的主要区别对比
如下表所示:
对比属性 | OLTP | OLAP |
---|---|---|
读特性 | 每次查询只返回少量记录 | 对大量记录进行汇总 |
写特性 | 随机、低延时写入用户的输入 | 批量导入 |
使用场景 | 用户,JavaEE后端项目 | 内部分析师,为决策提供支持 |
数据表征 | 最新数据状态 | 随时间变化的历史状态 |
数据规模 | GB,分库分表 | TB到PB |
2.2.1 关系建模
关系建模严格遵循第三范式(3NF),从图中可以看出,较为松散、零碎、物理表数量多,而数据冗余程度低
由于数据分布于众多的表中,这些数据可以更为灵活地被应用,功能性较强
关系模型主要应用于OLTP系统中,为了保证数据地一致性以及避免冗余,所以大部分业务系统的表都是遵循第三范式的(三范式是一个通用的标准,大部分公司都是遵循第三范式,不是一定遵循第三范式)
2.2.2 维度建模
维度模型主要应用于OLAP系统中,通常以某一个事实表为中心进行表组织,主要面向业务
特征是可能存在数据的冗余,但是能方便地得到数据,大大减少了join操作,提升了查询地执行效率
关系模型虽然冗余少,但是在大规模数据,跨表分析系统查询过程中,会造成多表关联,这会大大降低执行效率
所以我们通常采用维度模型建模,把相关各种表整理成两种:事实表和维度表
在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型
-
星型模型与雪花模型的区别主要在于维度的层级,标准的星型模型维度只有一层,而雪花模型可能会涉及多级
-
雪花模型比较靠近3NF,但是无法完全遵守,因为遵循3NF的性能成本太高
-
星座模型与前两种情况的区别是事实表的数据,星座模型是基于多个事实表
-
星座模型基本上是很多数据仓库的常态,因为很多数据仓库都是多个事实表的,所以星座不行做只反映是否有多个事实表,它们之间是否共享一些维度表,所以星座模型并不和前两个模型冲突
-
模型的选择
首先就是星座不星座,这个只跟数据和需求有关系,跟设计没关系,不用选择 星型还是雪花,取决于性能优先(星型模型),还是灵活性更优先(雪花模型) 目前实际企业开发中,不会绝对选择一种,根据情况灵活组合,甚至并存(一层维度和多层维度都保存)。但是整体来看更倾向于维度更少的星型模型。尤其是Hadoop体系,减少join就是减少shuffle,性能差距很大(关系型数据可以依靠强大的主键索引)
2.3 维度表和事实表(重点)
2.3.1 维度表
维度表一般是对事实的描述。每一张维度表对应现实世界中的一个对象或者概念
它是一个名词。例如:用户、商品、日期、地区、商家等
维度表的特征:
- 维表的范围很宽(具有多个属性、列比较多)
- 跟事实表相比,行数相对较小;通常<10万条
- 内容相对固定:编码表
思考题:维度表为什么需要这样设计?
维度是看待事实的角度,我们在设计的时候并不知道后续的分析业务有哪些
为了减少关联操作(join),提升性能,就会在一个维度表里面搞很多的字段
2.3.2 事实表
事实表中的每行数据代表一个业务事件(下单、支付、退款、评价等)
“事实”这个术语表示的是业务事件的度量值(可统计次数、个数、件数、金额等)
它是一个动词。例如:订单事件中的下单金额
每一个事实表的行包括:具有可加性的数值型的度量值、与维表相连接的外键、通常具有两个和两个以上的外键、外键之间表示维表之间多对多的关系
事实表的特征
:
- 非常的大,条数比较多
- 内容相对的窄:列数较少,具体多少看场景
- 经常发生变化,每天会新增加很多
2.3.2.1 事务型快照事实表
以每个事务或事件为单位,一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新
2.3.2.2 周期型快照事实表
周期型快照事实表中不会保留所有数据(不会保留每条数据的明细),只保留固定事件间隔的数据,中间的变化明细不关心,每天做一个全量
多长时间一个快照?
1天
2.3.2.3 累积型快照事实表
累积型快照事实表用于跟踪业务事实的变化,例如数据仓库中可能需要累积或者存储订单从下订单开始,到订单商品被打包、运输、签收的各个业务阶段的时间点数据来跟踪订单声明周期的进展情况,当这个业务过程进行时,事实表的记录也要不断更新
小结
在我们的实际数仓的场景中,很多情况都是汇总操作,我们在汇总的时候,往往会有一个观察这个问题的角度,比方时间(日,周,月,季度,年),地区(省,市,县),用户(性别,年龄区间等),类别等,这些都是维度,如果这些都直接关联在事实表周围,需要获取的时候,一次join就能搞定,比较方便…
周期快照事实表与累积快照事实表的区别?
周期快照事实表记录的是重复的可预测到的时间间隔的事实。一般周期快照的数据会按报表需要的周期进行记录,比较适合周期长一些的情况
累积快照适合用于较短周期,有着明确的开始和结束状态的过程。周期快照事实表记录上每个步骤的执行时间是逐步建立的,随着执行的过程逐步更新到事实表中
2.4 数据仓库建模(绝对重点)
建模工具:PowerDesigner/SQLYog/EZDML
2.4.1 ODS层
建模方式:关系建模,业务数据遵循三范式;日志数据就是把整个日志当成一个字段,之后在进行处理
- 保持数据原貌不做任何修改,起到备份数据的作用,外部表
- 数据采用压缩,减少磁盘存储空间
- 创建分区表,日期分区,防止后续的全表扫面
2.4.2 DWD层
DWD层需要构建维度模型,一般采用星型模型,呈现的状态一般为星座模型
数据清洗的手段?
sql、mapreduce、rdd、kettle、python(项目中采用sql进行清除)
清洗掉多少数据算合理?
1万条数据清洗掉1条
维度建模一般按照以下四个步骤:选择业务过程 → 声明粒度 → 确认维度 → 确认事实
-
选择业务过程
挑选感兴趣的业务线,就是选择事实表,但是为了防止后续增加需求,默认是把所有的事实表都会加载过来
先选事实表,一张事实表对应一条业务线
-
声明粒度
数据粒度指数仓的数据中保存数据的细化程度或综合程度的级别
一般来说,JavaEE过来的数据就是最小粒度,默认选择最小粒度(原始数据的粒度最小),如果做了加工整合,聚合操作,粒度才会发生变化
-
确认维度
维度的主要作用是描述业务的事实,主要表示的是“谁,何处,何时,因为什么,采用什么方式”等信息
(需要关联一些维度表,关联的方式就是维度表的外键id,维度表会做一些维度退化,扁平化处理)
-
确认事实
添加度量值,就是一些可以计算和统计的值,例如销售额、下单次数等
(度量值可以认为是可以计算、统计的值)
在DWD层,以业务过程为建模驱动,基于每个具体业务过程的特点,构建最细粒度的明细层事实表。
事实表可做适当的宽表化处理,我们把公共维度抽取出来,取数的时候用外键关联,但是如果某些维度是私有维度,那么你可以把这些维度写入事实表,或者是就是为了不join,提升取数的速度,也可以写入事实表,但是这样会存在数据冗余与一致性的问题
2.4.3 DWS层
统计各种主题对象相关的当天的一些指标,创建宽表
如何确认主题,我们可以从上面的维度里面找(注意:这只是一种方案),还有一种可行方案:按照部门划分,销售主题、财务主题、财务主题、市场主题、物流主题…
2.4.4 DWT层
对主题的一些指标统计出一些累积的指标,构建主题对象的全量宽表
DWS是按照天来聚合,DWT可以认为是按照最近1周/月/季度/年…这种累积来聚合
2.4.5 ADS层/APP层
就是为了不join,提升取数的速度,也可以写入事实表,但是这样会存在数据冗余与一致性的问题