为什么要构建数据仓库
-
首先数据仓库是一种分析数据库,用于存储和处理数据,以便对数据进行分析,也就是说做一些商业分析来辅助决策,那么就需要从不同的角度来观察数据,尤其涉及多个业务的分析,关系型数据表并不适合提供这样的分析。
-
其次就是对于公司来说,一般可能会有多个业务,而不同的业务平台,他的数据存储在不同的系统中,数据仓库可以整合不用系统的数据。
-
第三个就是数据类型问题,包括结构化数据、半结构化数据、非结构化数据,不同的数据类型的存储方式也不同,比如关系型数据库一般不存储日志数据
总结来说,就是将分散在各个系统的数据给他整合到一起,并做一些规范化处理和分析计算,提供一些数据支撑来辅助决策。
数仓分层的作用和意义
范式建模:其实一开始的数据仓库是没有分层的,比尔恩门最开始提出的数据仓库就是严格的按照三范式设计很多小表,然后分析的时候需要用到什么数据就去对应的表中找,这样就导致了效率很低性能很低。
维度建模:后来拉尔夫金博尔提出了维度建模(反范式),不严格按照三范式进行设计,虽然效率提高了,但是产生了大量的冗余数据。
所以为了结合范式建模和维度建模,提出了分层设计,不同层采用不同的建模方式,这样既保证了效率,又不会产生太多的数据冗余。更重要的是他可以减少重复计算,把一些计算的结果保存在中间层的表里面,后续使用的时候就不需要再计算一般了。
主要目的:通过对数据的规划,减少重复工作,提高整体计算效率。可能说单纯一个任务,直接写一个SQL从ODS层跑出来速度更快,但是如果有多个任务,可能就比较慢了,尤其是很多任务可能会对相同的数据重复提取,相当于每个任务都要跑一遍,这就会浪费大量算力和资源了。
介绍一下维度建模、范式建模
范式建模:就是严格按照三范式的要求来进行建模,通过实体关系模型(ER模型)来描述业务,不同的实体有不同的属性,并且实体和实体直接存在着关系,这个就说实体关系模型,比如用户和商品就是两实体。严格按照三范式来建模的话,一般就会生成很多小表,虽然减少了数据的冗余,但是查询效率会比较低。
维度建模:就是反范式建模,并不严格按照三范式要求进行建模,主要分为事实表和维度表,事实表就是业务过程,比如下单、退单等,包括维度列和度量列,这个维度列就是用来关联维度表的;按照维度表的设计不同,有星型模型、雪花模型、星座模型。星型模型的话就是一张事实表连接多张维度表;雪花模型在星型模型基础上维度表会进一步延展,也就是维度表还连接着下一层的维度表;星座模型是多张事实表连接多张维度表,并且有一些维度表是共用的。
三范式:
-
原子性,也就是每一列都是最小单位,不可再分,比如商品列(一部华为手机)可以分为两列:手机类型、还有数量
-
唯一性,非主键字段必须依赖于主键字段,不存在部分函数依赖关系,比如 学号| 姓名|学科|成绩就可以分成两张表学号|姓名 和学号|学科|成绩。
-
非主键字段不能相互依赖,不存在传递函数依赖,姓名|学校|学校地址 -----> 姓名|学校 学校|学校地址
业务总线矩阵是什么?
业务总线矩阵中包含维度模型所需的所有事实表以及维度表信息,也就是各个业务行为和各个维度,以及业务过程与维度的关系。业务总线矩阵的行是一个个业务过程,矩阵的列是一个个的维度,构建这个业务总线矩阵就能够清除看成各个业务行为需要用到哪些维度,方便设计维度模型。
粒度与维度
维度:指数据的分类特征或属性,也可以看着分析数据的角度,如用户维度、商品维度、地区维度
粒度:指是某个维度下数据的粗细程度,或者说事实表中一行数据所表达的业务细节程度,比如地区维度是按照省份统计还是按照城市统计、时间维度是按照月份统计还是按照天数统计。
原子指标、衍生指标、派生指标
原子指标:不可再分的最细粒度指标,比如交易金额,下单数量,用户数量。
派生指标:派生指标 = 原子指标 + 统计周期 + 业务+ 统计粒度,比如近一周各省份下单数量
衍生指标:利用公式二次计算的指标,比如比率,比例,均值。平均交易额,
ODS层是什么,怎么设计的
ODS层是数据操作层,直接存放采集到的数据,主要是将不同业务系统的数据汇总到一起。
数据来源可以分为业务数据和日志数据:
-
业务数据主要就是MySQL数据库导入的,全量数据是tsv格式,增量数据是json。
-
日志数据一般是json格式,就需要转化成结构化数据。
表的设计主要分为全量表和增量表:
-
全量表:通过DataX从数据库中采集,是tsv格式的结构化数据;
-
增量表:通过maxwell监控数据库的binlog采集,是json格式数据;日志数据flume采集存放为增量表。
压缩方式:采用gzip方法,Hadoop默认支持,压缩率极高,就是压缩/解压时间较长
存储格式:行式存储
分区策略:按照日分区
DIM层是什么,怎么设计的,拉链表是什么,拉链表怎么更新?
DIM层是公共维度层,主要存放通用的维度表,如用户维度表、地区维度表、品牌维度表、营销渠道维度表。
存储格式:orc列式存储(行式存储不利于统计分析)
压缩方式:snappy,压缩/解压时间短,有利于查询
表的设计可以分为全量表和拉链表:
-
全量表:因为维度表一般数据比较少,每天都保存一份全量表,并按照日分区。
-
拉链表:用户维度数据量比较大,每天保存一份全量表太浪费存储空间,所以采用拉链表,适用于缓慢变化的维度表。
拉链表的特点就是记录数据的历史状态,在原表的基础上增加了开始时间和介绍时间列,用来记录每条数据的开始和结束时间,
拉链表同步方法:
首日全量:(bootsrap),首日日期-'9999-12-31' 每日增量:(maxwell) insert的用户信息:当日日期-'9999-12-31' update用户信息:当日日期-'9999-12-31',原数据enddata改为当日日期-1,并放入对应分区(多次update取最后一次) 1.将旧表与新表通过union按行拼接 2.有两条数据表示发生了修改,修改前的数据标记为2,修改后和没修改的数据标记为1(窗口排序) 3.标记为2的数据end_date改为当日日期-1
数据来源:从增量表中获取数据,格式是json 分区策略:按照状态结束时间分区,最新数据保存在'9999-12-31'分区中。
DWD层是什么,有哪些事实表?明细层如何设计?
DWD是数据明细层,存放的是事实表,这是基于维度模型进行构建,对ODS层的数据进行加工处理,方便进行统计分析。
存储格式:列式存储orc+snappy压缩
事实表的设计主要分为不同的数据域:交易域、用户域、浏览域、工具域、互动域
一张事实表对应业务总线矩阵的一个业务过程,如
-
交易域:加购事务事实表、下单事务事实表、支付成功事务事实表、购物车周期快照事实表、交易流程累积快照事实表
-
用户域:用户注册事务事实表、用户登录事务事实表
-
工具域:优惠券使用(支付)事务事实表
-
互动域:收藏商品事务事实表
-
流量域:页面浏览事务事实表
设计:选择业务过程(订单事实表)-->声明粒度(每次下单)-->确定维度(时间、地区、商品、用户)-->确认实事
周期快照表和累积快照表是什么?有什么区别,为什么要用这个表?
周期快照事实表:记录某一个周期内的事实,用于分析存量型(例如商品库存,账户余额)或者状态型(空气温度,行驶速度)指标
-
对于商品库存、账户余额这些存量型指标,业务系统中通常就会计算并保存最新结果,所以定期同步一份全量数据到数据仓库,构建周期型快照事实表,就能轻松应对此类统计需求,而无需再对事务型事实表中大量的历史记录进行聚合了。
-
对于空气温度、行驶速度这些状态型指标,由于它们的值往往是连续的,我们无法捕获其变动的原子事务操作,所以无法使用事务型事实表统计此类需求。而只能定期对其进行采样,构建周期型快照事实表。
购物车周期快照事实表:对于购物车,每天可能都会发生加购减购,但是我们更关心的是每天结束时购物车有多少商品,比如后续需要计算各品类商品购物车存量Top3,就可以直接从周期快照事实表中获取数据。
累积快照事实表:主要用于分析业务过程之间的时间间隔等需求(如用户下单到支付的平均时间间隔)
交易流程累积快照事实表:就是将交易流程中多个行为状态数据累积在一张表中,这样免去了多张大表join的过程,计算快性能高,后续需要计算用户下单到支付的平均时间间隔,就可以直接从周期快照事实表中获取数据。
例如:从下单表支付表获取 下单时间、支付成功时间、下单到收货时间间隔 字段
DWS层是什么,有哪些表?
DWS是数据汇总层,对加工后的数据进行初步统计,减少计算。
存储格式:列式存储orc+snappy压缩
表的设计主要分为:
-
最近一日汇总表:
-
交易域:商品下单汇总、用户加购汇总、用户下单汇总、用户支付汇总、各省份订单汇总
-
用户域:用户注册汇总
-
工具域:优惠券使用汇总
-
互动域:收藏商品汇总
-
流量域:页面浏览汇总
-
-
最近n日汇总表:商品下单汇总、各省份订单汇总(7日、30日)
-
历史至今汇总表:用户下单汇总、用户登录汇总
ADS层是什么,有哪些表?
ADS层是数据应用层,建表根据具体需求而定,存放最终的统计结果
--需要将表同步到第三方存储MySQL
--存储格式:行式存储tsv,gzip压缩
--分区策略:不需要分区,统计结果的数据量不大
表的设计主要面向不同主题:流量、用户、商品、交易、优惠券主题
-
流量主题:各渠道浏览统计、路径分析(桑基图)
-
用户主题:流失用户数、用户留存率、用户新增及活跃、用户行为漏斗分析、新增下单用户数、近7日连续3日下单用户数
-
商品主题:近30日商品复购率、各品牌下单数、各商品下单数、各商品购物车存量Top3、各商品收藏数Top3
-
交易主题:下单到支付的平均时间间隔、各省份交易统计
-
优惠券主题:优惠券使用统计
如何保证数据一致性?
-
保证数据命名一致
-
保证数据口径一致(口径指取数逻辑,如新增用户数、活跃用户数如何计算?)
-
保证数据单位、字段类型一致
从需求分析、到命令规范、到开发规范、到指标监控都需要保证,
最后数据重新计算的场景一定保证后面依赖的部分全部计算.
数据仓库生命周期
一般ODS层会保留久一点,基本不会删除,所以其他层的数据都可以从ODS层恢复。
其他层的数据主要根据业务情况设置生命周期,比如有些指标最多就统计近7天的数据,那么7天之前的数据就可以删除了;有些指标统计近30天的数据,那么这些数据的生命周期就要大于30天。
数据量过大导致代码运行时间慢如何调优操作
-
合理进行数仓分层和数据表结构设计,避免过多的表关联
-
减少重复计算,对于一些统计查询,可以事先进行数据预聚合,保存到DWS层,如nd表数据从1d表读取
-
减少重复读取,如使用炸裂函数
数据湖
概念:数据湖是一个集中式的存储库,允许你以任意规模存储多个来源、所有结构化和非结构化数据,可以按照原样存储数据,无需对数据进行结构化处理,并运行不同类型的分析,对数据进行加工。
作用:数据仓库主要针对结构化和半结构化数据,对于非结构化的数据,如视频、音频就无法进行查询分析了。
为什么需要数据湖:当前基于 Hive 的离线数据仓库已经非常成熟,在传统的离线数据仓库中对记录级别的数据进行更新是非常麻烦的,需要对待更新的数据所属的整个分区,甚至是整个表进行全面覆盖才行,由于离线数仓多级逐层加工的架构设计,数据更新时也需要从贴源层开始逐层反应到后续的派生表中去。
场景题
1.从一个数组中求第N大的数
2.说一个你觉得有挑战性或者复杂性的数据倾斜例子
3.开发阶段,发现调度过程某些任务执行时间过长,导致无法再数据基线之前数据结果,需要怎么优化?
优化角度:sql优化,表优化,任务流程和集群资源优化,相关参数优化
- sql优化:不使用distinct改用group by;在获取数据列和行时设置尽量多where筛选条件;关联表过多时进行拆分;大表join小表使用mapjoin;其他数据倾斜处理方法。
- 相关表优化:根据表的数据特性判断是否分区;修改表压缩格式,例如多次读写的表采用snappy压缩,减少压缩和解压时间。
- 任务流程和集群资源优化:从任务流程上,设置任务优先级,保证核心任务的运行,减少资源抢占情况;从集群资源上,考虑增加内存,cpu和集群节点,扩大资源池。
- 相关参数优化:是否自动转化成maojoin,是否控制负载均衡,小文件合并,设置map和reduce内存大小...
4.数据治理阶段,发现投入产出比不高,怎么量化数据治理的产出价值?
5.查询100亿数据量的表,长时间卡在某个节点运行不动怎么处理?
说下查看logview找到对应节点表,其次查看任务执行引擎,查看执行分区和sql语句是有问题,在看是否有小表能进行mapjoin,如果是单独的热key倾斜,可以对热key拆分出来加上随机前缀。6.实时链路中,大促场景下数据积压,rps为100w,导致数据大屏不动了,上线前该怎么保障,临时处理该怎么处理,兜底方案该如何做?
提前做好压测,调整好任务资源,利用flink反压进制,增加消费者组和分区数提高消费能量,必要时准备实时双链路进行备用切换。
7.通常都是发现任务超时或者超过基线再去处理,如何在数据量激增,热key值不固定的情况下提前发现问题,减低超时风险
8.业务要求2条出报表,但是分层开发需要5天,并且要完成数据测试,请问怎么解决
9.一亿数据取最大1000条数据及其排名
select id,rn
from
(
select id,row_number()over(partition by id desc) as rn
from
(
sekect id #获得每个分区内的前1000个id
from
(
select id,row_number()over(partition by hash(id)%10000 order by id desc) as rn
from table
where day='20250101'
)a where rn<=1000
)b
)c where rn<1000