一、数仓建模
1、为什么要做数仓分层
分层是站在数仓全集的视角,对于一系列的计算过程抽象出通用的职责,规定每一层只做某些职责,每一层有自己独特的命名,并且不同层之间有明确的前后关系。
-
持久化可以用空间换时间,节省计算资源。通过分层的数据预处理,能够更快满足应用的取数效率;增加了复用性,进而带来一致性的提升和开发效率的提升。
-
分层处理数据,隔离变化,降低维护成本,从合作层面可以统一建设思路。基础层只做数据整合清洗,高级层关注业务规则,应用层面向数据应用,一个复杂工作拆分成多个层级关系清晰的简单任务,每一层的任务逻辑都相对简单且容易理解,当数据变动时,因为层与层分离,只需变动一小块。如果不分层,业务规则变动时,工作将十分麻烦,影响巨大,不宜处理。
-
良好的数据流向,血缘清洗,为之后面向仓库的管理优化提供便利。
每一层的作用:
数仓层次 | 说明 | 作用 |
---|---|---|
ods层 (源数据接入层) | 存储数据仓库的源接入数据,分为两类:
ods作为数据缓冲层,是源系统的备份,粒度与源系统保持一致,一般实时或者类实时加载数据。ods层一般提供操作型报表(不推荐),此类报表应该是只关注当前数据,不关注历史的。除开发使用,排查case使用,ods层不允许用户直接访问进行数据分析。 | 1)制定ods存储规则,(增量/全量/快照); |
dw基础明细层 | 存储数据仓库的最底层明细数据,不面向分析,该层数据与ods源数据粒度相同,是对ods做过过滤、清洗、转化后统一的规整的数据存储,将分库分表的数据或者多业务线的数据做行级别的数据集合。 | 1)清洗ods数据,如ods中存在的一些软删除数据; |
dw基础汇总层 | 该层存储对明细数据的维度汇总数据,这里的维度包括(日期维度,业务维度等),通过明细层聚合,基于明细层的一些指标基本在这一层定型(如pv,计费单位等),形成汇总层数据。 通常用维度建模构建星型模型、雪花模型、星座模型。 | 采用维度建模,事实表中需要包含主要分析维度的主键(包含较少的维度属性值),事实的是完全可加的事实,对于复合指标如比率,乘积,分子分母需要分开存储。 注:不同粒度的事实存储不同的事实表中。 |
dm主题层 | 主题层表加入业务逻辑,直观反应业务问题建模的多维聚合的宽表。 1) 采取反范式设计,为方便使用以宽表的形式提供 由于分析粒度的不同,主题层表可以有内部依赖。 | 1)一类是主题归并(基于基础事实表和维度表,在相同粒度、维度上合并)的宽表; |
rpt应用层 | 存储面向报表和数据产品应用的数据,包括(数据应用系统模型、报表模型等),该层模型面向应用,怎么好用怎么建,可以不同粒度事实在一个表,也可以不同粒度数据在一个表。 | 1)考虑应用特性,选择应用存储类型 |
2、范式建模(简单易懂的说明 数据库三大范式(通俗易懂)_第一二三范式怎么区分-CSDN博客)
-
第一:列独立 数据库表的每一列都是不可分割的原子数据项
-
第二:有主键 要求数据库表中的每个实例或记录必须可以被唯一地区分
-
第三:不冗余 任何非主属性不依赖于其它非主属性(在2NF基础上消除传递依赖)
3、维度建模
过程:梳理维度x指标矩阵,自顶向下倒退模型所需字段、所需维表。维度表的拆分可以考虑稳定性、业务特性。
雪花模型和星型模型的区别:
4、数据域
-
业务过程为企业活动中不可拆分的行为事件,是一个动作,如下单、支付、退款。通过业务过程对模型进行分类管理,是辅助理解业务链条的重要手段。
-
数据域是若干个业务过程的集合,是用于分类管理业务过程的一级概念。数据域既有以对象为限定的命名(比如商品/会员),也有对动作事件的命名(交易、互动),还有对范围限定的命名(广告、分销),可见数据域不是一个对系统的完美划分(划分指无歧义不重不漏)。数据域冲突时:
-
第一条是动作在哪往哪放,比如店铺的开店,这放在店铺域;但店铺的曝光,就放在日志域;店铺的发券就放在工具和服务域,所以核心是动作的分类,不是主体对象的分类。
-
第二条是特殊大于一般,比如广告的曝光点击就不放在日志域而放到广告域,而商品的评论放在商品域也优先于互动域,这说明同样的动作,具有特殊大于一般的性质,划入精确空间优先于划入粗略空间。
-
-
按照阿里的理论,先划分业务线再划分数据域,数据集市更多是范围上的划分。
拉链表:缓慢变化维 https://blog.51cto.com/u_150537/4030985
数据湖:数据湖可存储结构化和非结构化数据,是一种面向大规模、多来源、高度多样化数据的组织方法。特点是存算分离。iceberg、hudi 数据湖初探(一) - 知乎
二、数据治理
数仓的目标:效率高、质量好、成本低、有价值。
效率、质量、成本、安全、元数据
1、计算优化
2、存储优化
3、指标管理
4、质量:准确性、合理性、一致性、及时性
三、组件原理
MAPREDUCE
Hadoop MapReduce介绍、官方示例及执行流程 - 知乎
SPARK
https://www.cnblogs.com/0xcafedaddy/p/7614299.html
shuffle过程:
Shuffle有两个计算阶段,Map阶段和Reduce阶段。我们要重点掌握Map阶段的计算流程,我把它总结为4步:
- 对于分片中的数据记录,逐一计算其目标分区,然后填充内存数据结构(PartitionedPairBuffer或PartitionedAppendOnlyMap);
- 当数据结构填满后,如果分片中还有未处理的数据记录,就对结构中的数据记录按(目标分区ID,Key)排序,将所有数据溢出到临时文件,同时清空数据结构;
- 重复前2个步骤,直到分片中所有的数据记录都被处理;
- 对所有临时文件和内存数据结构中剩余的数据记录做归并排序,最终生成数据文件和索引文件。
在Reduce阶段我们要注意,Reduce Task通过网络拉取中间文件的过程,实际上就是不同Stages之间数据分发的过程。并且,Shuffle中数据分发的网络开销,会随着Map Task与Reduce Task的线性增长,呈指数级爆炸。
最后,从硬件资源的角度来看,Shuffle对每一种硬件资源都非常地渴求,尤其是内存、磁盘和网络。由于不同硬件资源之间的处理延迟差异巨大,我们很难在Shuffle过程中平衡CPU、内存、磁盘和网络之间的计算开销。因此,对于Shuffle我们避之唯恐不及,要能省则省、能拖则拖。
groupbykey和reducebykey都有做shuffle,reduce还有做聚合。
内存管理:
首先是内存的管理方式。Spark区分堆内内存和堆外内存:对于堆外内存来说,Spark通过调用Java Unsafe的allocateMemory和freeMemory方法,直接在操作系统内存中申请、释放内存空间,管理成本较高;对于堆内内存来说,无需Spark亲自操刀而是由JVM代理。但频繁的JVM GC对执行性能来说是一大隐患。另外,Spark对堆内内存占用的预估往往不够精确,高估可用内存往往会为OOM埋下隐患。
其次是统一内存管理,以及Execution Memory和Storage Memory之间的抢占规则。它们就像黄四郎招租故事中黄小乙和张麻子的田地,抢占规则就像他们之间的占地协议,主要可以分为3条:
- 如果对方的内存空间有空闲,那么双方都可以抢占;
- 对RDD缓存任务抢占的执行内存,当执行任务有内存需要时,RDD缓存任务必须立即归还抢占的内存,其中涉及的RDD缓存数据要么落盘、要么清除;
- 对分布式计算任务抢占的Storage Memory内存空间,即便RDD缓存任务有收回内存的需要,也要等到任务执行完毕才能释放。
最后是不同代码对不同内存区域的消耗。内存区域分为Reserved Memory、User Memory、Execution Memory和Storage Memory。其中,Reserved Memory用于存储Spark内部对象,User Memory用于存储用户自定义的数据结构,Execution Memory用于分布式任务执行,而Storage Memory则用来容纳RDD缓存和广播变量。
小文件问题:
原因:
1、数据源本身含大量小文件
2、动态分区插入数据,没有Shuffle的情况下,输入端有多少个逻辑分片,对应的HadoopRDD就会产生多少个HadoopPartition,每个Partition对应于Spark作业的Task(个数为M),分区数为N。最好的情况就是(M=N) && (M中的数据也是根据N来预先打散的),那就刚好写N个文件;最差的情况下,每个Task中都有各个分区的记录,那文件数最终文件数将达到M * N个。这种情况下是极易产生小文件的。
3、动态分区插入数据,有Shuffle的情况下,上面的M值就变成了spark.sql.shuffle.partitions(默认值2000)这个参数值,文件数的算法和范围和2中基本一致。
导致的问题:
对于HDFS
从 NN(namenode) RPC请求角度,文件数越多,读写文件时,由于要和namenode进行通信,在namenode压力大且文件数过多时,会极大的消耗时间。
从 NN 元数据存储角度,文件数越多,NN存储的元数据就越大。
对于下游流程
下游流程,不论是MR、Hive还是Spark,在划分分片(getSplits)的时候,都要从NN获取文件信息。这个过程的耗时与文件数成正比,同时受NN压力的影响。在NN压力大,上游小文件多的情况下,下游的getSplits操作就会比较慢。
主要通过参数优化:
阶段1:map合并,发生在split操作,可以解决输入小文件的合并(也可以解决只有map阶段的输出小文件合并),方式是把多个小文件合并成一个数据分片(split),进而交给一个map task进行计算。
阶段2:reduce合并,发生在shuffle阶段,可以解决输出小文件的合并,方式是减少reduce task数量,减少小文件的形成
阶段3:写入hdfs之后,可以解决输出小文件的合并,方式是额外启动一个job,根据用户设置的阈值来合并已经生成的小文件
执行过程:
1、Spark SQL 任务执行过程
Spark 完成一个数据生产任务(执行一条 SQL )的基本过程可以概括为语法树解析-逻辑分析-语法优化-计划执行。
(1)对SQL进行语法分析,生成逻辑执行计划。
(2)从 Hive metastore server 获取表信息,结合逻辑执行计划生成并优化物理执行计划。
(3)根据物理执行计划向 Yarn 申请资源(executor),调度 task 到 executor 执行。
(4)从 HDFS 读取数据,任务执行,任务执行结束后将数据写回 HDFS。
2、RDD、宽窄依赖
如上图表示方框表示RDD,实心矩形表示分区(partitions)
1,窄依赖表示的是子RDD的分区只是到父RDD的分区(一对一)
2,宽依赖表示的是子RDD的分区到父RDD的多个分区(多对多),就会产生shuffer操作
调优方法
自带的:
CBO:意为基于代价优化策略,它需要计算所有可能执行计划的代价,并挑选出代价最小的执行计划。
RBO:对数据是不敏感的,是基于规则的,比如谓词下推、列剪枝。
HBO:基于历史信息的优化。
AQE:AQE是Spark SQL的一种动态优化机制,在运行时,每当Shuffle Map阶段执行完毕,AQE都会结合这个阶段的统计信息,基于既定的规则动态地调整、修正尚未执行的逻辑计划和物理计划,来完成对原始查询语句的运行时优化。
人为的:HiveSQL常用优化方法全面总结_hive sql优化-CSDN博客
https://www.cnblogs.com/0xcafedaddy/p/7614299.html
KAFKA
FLINK
watermark水位机制:
ACK机制 :将 Acker 开启后,如果下游某一个 Bolt 处理失败或超时未完成,上游会重发数据,以此保证数据至少被成功处理一次(至少一个相应的 ACK 被接收),即 At Least Once 语义
检查点机制 :数据流中按照固定方式插入 barrier ,对于一个 task ,每经过一个 barrier ,将创建检查点,当前的状态会以快照的形式进行存储。当发生处理失败等情况时,会从上一个检查点的快照开始再次,将相应 barrier 后的数据再次处理。当一个 task 有多个输入源时,来自不同输入源的 barrier 未对齐,可能导致其中一些输入源的数据被多次处理,即 At Least Once 语义;若进行 barrier 对齐,则为 Exactly Once 语义。
DORIS
优点 | 缺点 | 适用场景 | |
---|---|---|---|
Doris | 1.同时支持 高并发点查询和高吞吐的Ad-hoc查询 2.同时支持 批量导入和近实时mini-batch导入 3.同时支持 明细和聚合查询 4.兼容Mysql协议和标准SQL 5.支持Rollup Table 和Rollup Table的智能查询路由 6.支持多表Join和灵活的表达式查询 7.支持Schema 在线变更 8.支持和Hash和Range二级分区 | 1.Doris 目前不支持如 update 或 insert 等操作单条数据的 DML 语句 2.不支持实时导入 3.不支持精确去重的物化索引 4.RollUP表需要逐个手动建立 | 1.Doris的聚合模型主要用于固定模式的报表类查询场景,实现原理和Mesa完全一致 2.百毫秒的高性能OLAP查询 4.大结果集查询 5.明细查询 |
Kylin |
|
| 1.固化查询:指标提取、多维分析、dashboard等 2.查询模式比较固定、SQL表达 3.数据规模大、指标数量多、去重指标要求精确 4.查询并发度高对响应时间要求比较严苛 |
Druid |
|
| 1.时序型数据的实时OLAP分析 2.不关心事件明细 3.数据产生速率快、原始数据量大 4.以简单指标(sum/count/min/max)为主,去重指标不多(1~2个) |