转:OLAP数仓从百万到百亿级数据量实时分析 (4)

转:OLAP数仓从百万到百亿级数据量实时分析

(1)Join执行方式
根据参与Join的驱动表(Build Table)和被驱动表(Probe Table)的大小,Hash Join一般可分为broadcast和partition两种。

转:OLAP数仓从百万到百亿级数据量实时分析

广播方式适用于大表与小表进行Join,在并行Join时,将小表广播到大表分区数据所在的各个执行节点,分别与大表分区数据进行Join,最后返回Join结果并汇总。

转:OLAP数仓从百万到百亿级数据量实时分析

而分区方式是最为一般的模式,适用于大表间Join或表大小未知场景。分别将两表进行分区,每个分区分别进行Join。

转:OLAP数仓从百万到百亿级数据量实时分析

显然,判断大小表的关键就看是否能够通过某种方式获取表的记录数,如果存储层保存了记录数,那么可从元数据中直接获取。
如果Join的两表都是大表,但至少有个表是带Where过滤条件的,那么在决定走分区方式前还可进一步看满足条件的记录数,这时候,物理上进行分区的表存储方式可发挥作用,可以看每个分区的最大值和最小值及其记录数来估算过滤后的总记录数。当然,还有种更精确的方式是列直方图,能够直接而直观得获取总记录数。
如果上述的统计信息都没有,要使用CBO还有另一种方式就是进行记录的动态采样来决定走那种Join方式。
(2)Join顺序
如果一个查询的SQL中存在多层Join操作,如何决定Join的顺序对性能有很大影响。这块也已是被数据库大佬们充分研究过的技术。

转:OLAP数仓从百万到百亿级数据量实时分析

一个好的CBO应该能够根据SQL 语句的特点,来自动选择使用Left-deep tree(LDT,左图)还是 bushy tree(BYT,右图)执行join。
两种Join顺序没有好坏之分,关键看进行Join的表数据即Join的字段特点
对于LDT,如果每次Join均能够过滤掉大量数据,那么从资源消耗来看,显然是更优的。对于给每个列都构建了索引的某些系统,使用LDT相比BYT更好。
一般来说,选择BYT是效率更高的模式,通过串行多层Join改为并行的更少层次Join,可以发挥MPP架构的优势,尽快得到结果,在多表模式ROLAP场景常采用。

为什么需要向量化执行引擎?其与动态代码生成有何关系?

查询执行引擎 (query execution engine) 是数据库中的一个核心组件,用于将查询计划转换为物理计划,并对其求值返回结果。查询执行引擎对系统性能影响很大,在一项针对Impala和Hive的对比时发现,Hive在某些简单查询上(TPC-H Query 1)也比Impala慢主要是因为Hive运行时完全处于CPU bound的状态中,磁盘IO只有20%,而Impala的IO至少在85%。
什么原因导致这么大的差别呢?首先得简单说下火山模型的执行引擎。

(3)火山模型及其缺点

火山模型(Volcano-style execution)是最早的查询执行引擎,也叫做迭代模型 (iterator model),或 one-tuple-at-a-time。在这种模型中,查询计划是一个由operator组成的DAG,其中每一个operator 包含三个函数:open,next,close。Open 用于申请资源,比如分配内存,打开文件,close 用于释放资源,next方法递归的调用子operator的 next方法生成一个元组(tuple,即行row在物理上的表示)。
下图描述了“select sum(C1) from T1 where C2 > 15”的查询计划,该查询计划包含Project,HashAgg,Scan等operator,每个 operator的next方法递归调用子节点的 next,一直递归调用到叶子节点Scan operator,Scan operator的next 从文件中返回一个元组。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwszsj.html