全面的关于OLAP数仓总结
点击上方蓝字关注我们
有哪些类型的OLAP数仓?
按数据量划分
按建模类型划分
1、MOLAP
2、ROLAP
3、HOLAP
4、HTAP
有哪些常用的开源ROLAP产品?
宽表模型
多表组合模型
有哪些黑科技用于优化ROLAP系统性能?
什么是MPP架构?
1、MR架构及其局限
每个MapReduce 操作都是相互独立的,Hadoop不知道接下来会有哪些MapReduce。
每一步的输出结果,都会持久化到硬盘或者HDFS 上。
2、MPP优缺点分析
用户通过Impala提供的impala-shell或beeline等客户端/UI工具向Impala节点下发查询SQL;接收该SQL的Impala节点即为Coordinator节点,该节点负责进行SQL解析;
首先产生基于单节点的执行计划;再对执行计划进行分布式处理,比如将Join、聚合(aggregation)等并行化到各Impala Executor节点上。执行计划被切分为多个Plan Fragment(PF),每个PF又由一到多个Operator组成;
接着,下发经过优化后的执行计划的PF到对应的Executor节点,多个执行节点并行处理任务,缩短整个任务所需时间;
执行节点扫描HDFS/Hbase等存储上的数据,并逐层进行处理,比如进行跨节点的数据shuffe,Join等操作;
执行节点完成任务并将输出结果统一发送到Coordinator节点;
Coordinator节点汇总各个执行节点数据,做最后处理,最终返回给用户想要的结果集。
PF之间的数据交互(即中间处理结果)驻留在内存Buffer中不落盘(假设内存够大);
Operator和PF间基于流水线处理,不需要等上一个Operator/PF都完成后才进行下一个处理。上下游之间的关系和数据交互式预先明确的。
中间结果不落盘,在正常情况下是利好,但在异常情况下就是利空,这意味着出现节点宕机等场景下,需要重新计算产生中间结果,拖慢任务完成时间;
扩展性没有MR等架构好,或者说随着MPP系统节点增多到一定规模,性能无法线性提升。有个原因是“木桶效应”,系统性能瓶颈取决于性能最差的那个节点。另一个原因是规模越大,出现节点宕机、坏盘等异常情况就会越频繁,故障率提高会导致SQL重试概率提升;
4、其他非MPP架构
什么是基于代价的查询优化?
基于规则优化
基于代价优化
为什么需要向量化执行引擎?其与动态代码生成有何关系?
火山模型及其缺点
大量虚函数调用:火山模型的next方法通常实现为一个虚函数,在编译器中,虚函数调用需要查找虚函数表, 并且虚函数调用是一个非直接跳转 (indirect jump), 会导致一次错误的CPU分支预测 (brance misprediction), 一次错误的分支预测需要十几个周期的开销。火山模型为了返回一个元组,需要调用多次next 方法,导致昂贵的函数调用开销
类型装箱:对于a + 2 * b之类表达式,由于需要对不同数据类型的变量做解释,所以在Java中需要把这些本来是primitive(如int等类型)的变量包装成Object,但执行时又需要调用具体类型的实现函数,这本质上也是虚函数调用的效率问题;
CPU Cache利用效率低:next方法一次只返回一个元组,元组通常采用行存储,如果仅需访问第一列而每次均将一整行填入CPU Cache,将导致Cache Miss;
条件分支预测失败:现在的CPU都是有并行流水线的,但是如果出现条件判断会导致无法并行。比如判断数据的类型(是string还是int),或判断某一列是否因为其他字段的过滤条件导致本行不需要被读取等场景;
CPU与IO性能不匹配:每次从磁盘读取一个行数据,经过多次调用交给CPU进行处理,显然,大部分时间都是CPU等待数据就绪,导致CPU空转。
向量化执行引擎
动态代码生成
都有哪些存储空间和访问效率优化方法?
数据压缩和编码
数据精细化存储
数据分区:数据分区可用于将表中数据基于hash或range打散到多个存储节点上,配合多副本存储。可以提高数据容灾和迁移效率。除此之外,在查询时可以快速过滤掉不符合where条件要求的数据分区,无需逐列读取数据进行判断。
行组:与数据分区类似,Hadoop中常用的parquet和orcfile还将表数据分为多个行组(row group),每个行组内的记录按列存储。这样即达到列存提高OLAP查询效率,同时能够兼顾查询多行的需求;
局部索引:在数据分区或行组上创建索引,可以提高查询效率。如下图所示,orcfile在每个行组的头部维护了Index Data来,保存最大值和最小值等元数据,基于这些信息可以快速决定是否需扫描该行组。某些OLAP系统进一步丰富了元数据信息,比如建立该行组记录的倒排索引或B+树索引,进一步提高扫描和查询效率。
富元数据:除了提供最大值和最小值信息外,还可进一步提供平均值、区分度、记录数、列总和,表大小分区信息,以及列的直方图等元数据信息。
数据本地化访问
<property>
<name>dfs.client.read.shortcircuit</name>
<value>true</value>
</property>
<property>
<name>dfs.domain.socket.path</name>
<value>/var/lib/hadoop-hdfs/dn_socket</value>
</property>
运行时数据过滤
同时下发两个表的SCAN操作。左边是大表,右边是小表(相对而言,也有可能是同等级别的),但是左表会等待一段时间(默认是1s),因此右表的SCAN会先执行;
右表的扫描的结果根据join键哈希传递扫不同的Join节点,由Join节点执行哈希表的构建和RF的构建;
Join节点读取完全部的右表输入之后也完成了RF的构建,它会将RF交给Coordinator节点(如果是Broadcast Join则会直接交给左表的Scan节点);
Coordinator节点将不同的RF进行merge,也就是把Bloom Filter进行merge,merge之后的Bloom Filter就是一个GLOBAL RF,它将这个RF分发给每一个左表Scan;
左表会等待一段时间(默认1s)再开启数据扫描,为了是尽可能的等待RF的到达,但是无论RF什么时候到达,RF都会在到达那一刻之后被应用;
左表使用RF完成扫描之后同样以Hash方式交给Join节点,由Join节点进行apply操作,以完成整个Join过程。