本文由百度智能云高级产品经理——鲁志敬 在百度开发者沙龙线上分享的演讲内容整理而成。内容深度解读Polo产品的技术架构与产品特性。希望本次分享能够让听众对Palo有一个基本认识,并掌握一定的数据仓库设计方法。
文:鲁志敬
视频回放:https://developer.baidu.com/l...
本次分享的主题是:百度数据仓库Palo技术特性解读。内容主要分为以下三个方面:
- 产品介绍与发展历程
- 应用场景介绍
- Palo技术特性解读
01产品发展历程
百度数据仓库Palo 是基于业内领先的OLAP数据库 Apache Doris(Powered By Apache Doris) 构建的MPP架构云数据仓库,致力于帮助企业快速且低成本地构建极速易用的云上数据分析平台,加速企业数智化进程。
- 支持标准SQL并完全兼容MySQL协议
- 仅需秒级甚至毫秒即可返回海量数据下的查询结果
- 有效支持多维分析、实时分析、交互式分析等多种数据分析场景
发展历程
阶段一:助力内部业务
Palo的历史可以追溯到2008年,当时是解决百度凤巢统计报表的专用系统,随着百度业务飞速发展,内部对系统进行了多次迭代,逐渐承担起百度内部业务的统计报表和多维分析需求,成为百度内部第一个OLAP分析平台。
阶段二:做大做强
2013 年,Palo进行了 MPP 框架的升级,2017 以百度 Palo 的名字在 GitHub 上进行了开源,于此同时在百度智能云上发布了云端托管服务“百度数据仓库Palo”。2018 年把Palo贡献给 Apache 基金会,更名为Apache Doris。
02应用场景
数据分析需求的演进趋势
- 查询结果可以快速响应
提升查询效率一直是分析型数据库发展的第一动力。从过去查询一个报表、跑SQL需要半个小时、几十分钟到现在的秒级甚至毫秒级,这给带来效率的提升是巨大的。 - 实时业务洞察
数据价值会随时间推移而降低,T+1已经不能满足业务对高时效性的要求。 - 灵活需求应对
业务趋势预知与系统建设滞后的矛盾,需求交付周期较长。 - 全民化的数据探索
更低的分析门槛和学习成本,更高的并发支持。
Palo在企业大数据体系中的多种应用场景
- 数仓查询加速
解决传统数仓和数据平台查询效率低下的困境,达到海量数据低至毫秒/秒级查询耗时,海量数据无缝应用,极大幅度加速数据决策效率。
- 实时数仓构建
支持流式数据高效导入、业务指标实时聚合,保证业务数据得以实时洞察,并可以减少数据处理链路、统一数据流向,简化大数据平台架构。
- 多源联邦查询
构建跨多个数据源的统一查询入口,实现实时数据和离线数据的联邦分析,满足数据分析人员更多元化的查询需求。
- 交互式数据分析
以借助一些BI可视化工具的能力去构建交互式数据分析应用,对海量数据进行自助探查和多维度分析,实现对业务的深层探索和快速决策。
03技术特性解读
系统架构
在架构方面,Palo只有两个主进程模块。一个是 Frontend(FE),另一个是Backend(BE)。
- Frontend(FE)
可以理解为Palo 的管控节点,主要负责用户请求的接入、查询计划的解析、元数据的存储和集群管理相关工作。
- Backend(BE)
主要负责数据存储、查询计划的执行。
这两类进程都是可以横向扩展的。除此之外,Palo不依赖任何第三方系统(如 HDFS、Zookeeper等)。这种高度集成的架构设计极大的简化了一款分布式系统的运维成本。
极致性能背后的核心技术
对于一个分析型数据库,最核心的三个组成部分就是存储引擎、查询引擎和查询优化器,这也是Palo极致性能的决定因素。
存储引擎
- 存储格式:列式存储
在分析场景,列存往往只会读取需要的列,跳过无用数据,会比行存扫描更少的数据量,减少IO开销以提高性能。
同时数据按照列进行连续存储,因为类型相同,因此可以获得极高的压缩率,节省磁盘空间。
- 自适应编码
对不同的列类型还提供了不同的编码方式,如 INT 类型会使用 BitShuffle 的编码方式,而字符串类型会使用字典编码。更进一步的,Palo还会自动根据列的值来切换编码类型。
在编码基础上还进一步通过LZ4算法进行压缩,最高提供1:8的数据压缩比。也就是说,10G数据进入Palo可能只占用1G多,这样可以极大节省磁盘空间。
这种列式的存储组织形式还为上层计算的性能优化提供了很大的便利,特别是在向量化查询和延迟物化等方面。
- 文件组织
文件组织形式上,Palo的文件格式和 Parquet 比较类似。一个数据版本会被分割成最大 256MB 一个的 Segment,每个 Segment 对应一个物理文件。
Segment 通常分为 Header、DataRegion、IndexRegion、Footer 这几个区域。
Data Region 用于按列存储数据,每一列又被分为多个 Page。
Index Region 则负责存储数据的索引,Palo提供了丰富的索引结构来帮助加速数据的读取和过滤。
- 索引类型
索引的类型大体可以分为智能索引和二级索引两种,其中智能索引是在 Palo 数据写入时自动生成的,无需用户干预,包括前缀稀疏索引、Min Max索引等。而二级索引是用户可以选择性的在某些列上添加的辅助索引,需要用户自主选择是否创建,比如像Bloom Filter、BitMap倒排索引等。
查询引擎
Palo的查询引擎是基于 MPP 的火山模型,是从早期版本的 Apache Impala 演化而来,也是在各种数据库系统中应用最广泛的模型。
- Exchange节点
相对于一些分布式 Gette-Setter 框架,最显著的区别在于其实现了 Exchange 节点。
在Palo中,一个SQL语句会先生成一个逻辑执行计划,然后根据数据的分布,形成一个物理执行计划。
物理执行计划会有多个 Fragment,而 Fragment 直接的数据传输则是由 Exchange 节点完成的。
有了 Exchange 节点,最大的收益是整个查询框架拥有了数据 Reshuffle 的能力,通过这个能力,查询的计算节点不在局限于数据的存储节点,从而能够更好的利用多节点资源进行并行数据处理。
在Palo中,物理执行计划中的 Fragment 会被发往多个 BE 节点并行执行。不同 Fragment 之间的数据通过 Exchange 节点,根据规则 Shuffle 到对应的上层 Fragment 中。
除了节点间并行,Palo还支持在一个节点内部继续拆分 Fragment,从而进行节点内的并行执行,以充分利用一个节点上的多 CPU 资源。
- 算子优化
除了整体的执行框架通过并行设计来提高查询效率外,Palo还对很多具体的查询算子进行了优化。
最典型的就是聚合算子和Join算子。
聚合算子是一种阻塞型的算子,他需要等到全部数据处理完成后,才会将数据发送给上层节点。
在Palo,聚合算子会被拆分成两级聚合。第一级聚合会在数据所在节点先进行一次本地聚合,来减少发送到第二层聚合时需要传输的数据量,而第二层聚合会将相同的 Key 汇聚到同一个节点,进行最终的聚合计算。
在第一级聚合算子中,如果发现数据的聚合效果很低,即使聚合后也无法有效降低需要传输的数据量时,则会自动的停止第一级聚合,而将算子转换为一个非阻塞的流式算子,直接将读取到的数据发送到上层节点,从而避免了不必要的阻塞等待时间。
针对 Join 算子,Palo也进行了大量优化,其中Runtime Filter 是其中很重要的一种优化方式。
在两个表的 Join 操作中,我们通常将右表称为 BuildTable,而左表称为 ProbeTable。
在实现上:
- 首先读取右表的数据,在内存中构建一个 HashTable(Build)。
- 读取左表的每一行数据,并在 HashTable 中进行连接匹配,来返回符合连接条件的数据。
通常来说,左表的数据量会大于右表的数据。
Runtime Filter 的设计思路:
在右表构建 HashTable 的同时,为连接列生成一个过滤结构。之后把这个过滤列结构下推给左表。这样一来,左表就可以利用这个过滤结构,对数据进行过滤,从而减少 Probe 节点需要传输和比对的数据量。这种过滤结构被称为 Runtime Filter。
针对不同的数据,Palo也实现了不同的 Filter 类型,如 In Predicate,Bloom Filter 和 Min Max,用户可以根据不同场景进行选择。
Runtime Filter 可以适用于大部分 Join 场景,包括节点的自动穿透,将 Filter 穿透下推到最底层的扫描节点,或者在分部的 Shuffle Join 中,将多个节点产生的 Filter 进行合并后再下推等。
向量化执行引擎
向量化执行引擎,顾名思义,向量化就是算法从一次对一个值进行运算转换为一次对一组值进行运算的过程。
向量化执行引擎有以下几方面的优势:
- 减少火山模型中的虚函数调用数量;
- 以块为单位处理数据,提供了cache命中率,从Cache中读取数据和从内存中读取数据,性能有10-100倍提升;
- 多行并发处理,契合了CPU乱序执行与并发执行的特性。
- 同时处理多行数据,使SIMD有了用武之地。
在Palo中我们正在开发全新的向量化执行引擎,目前已经实现宽表模型上的向量化查询,Join和存储层向量化正在开发中,预计2021年底就可以全面实现向量化。
查询优化器
对于一个SQL查询,会在SQL词法和语法解析完成后生成抽象语法树,再进一步转换成关系代数表达式,然后生成逻辑执行计划。
查询优化器主要用于从逻辑执行计划到物理执行计划的转换,生成最优的执行计划交由查询引擎执行。在这个过程中查询优化器的作用在很大程度上决定了查询性能。
基于规则优化RBO就是会将原有表达式裁剪掉,遍历一系列规则 (Rule),只要满足条件就转换。而基于代价优化CBO会将原有表达式保留,基于统计信息和代价模型,生成最小的执行计划。
Palo查询优化器能够同时进行基于规则和基于代价的查询优化,这里我们简单列了一些优化点,例如常量折叠、子查询改写、谓词下推以及Join Reorder、Colocate Join和Bucket Shuffle Join 等。
04简单易用
通过上述在查询引擎、存储引擎以及查询优化器上做的诸多优化,实现了极致的查询性能。但性能不是数据库的全部,对用户来说,易用性才是决定是否持续使用的关键,Palo从系统设计之初就一直以用户的易用性作为出发点。
从一个用户分析的全周期来看,一般可以简单归纳成四个方面,从数据建模→数据导入→用户上手分析→持续使用以及维护升级,Palo的易用性无处不在。
数据建模
通过这个建表语句,就能快速建立起分布式表。相对于MySQL建表语句,在Palo中只增加了一些分布式系统所具有的特性,比如分区分桶等,有过分布式使用经验的非常易于上手,就算没有使用过也能快速掌握。
Palo目前支持三类数据模型:
- Aggregate 模型
可以通过预聚合,极大地降低聚合查询时所需扫描的数据量和查询的计算量,非常适合有固定模式的报表类查询场景。 - Unique Key模型
针对需要唯一主键约束的场景,可以保证主键唯一性约束主键唯一模型,实现精准去重和行级别数据更新; - Duplicate 模型
可以保留全量明细数据,适合任意维度的 Ad-hoc 查询。虽然同样无法利用预聚合的特性,但是不受聚合模型的约束,可以发挥列存模型的优势。
物化视图是将预先计算(根据定义好的 SELECT 语句)好的数据集,存储在一个对用户透明却有真实数据的视图表格中。
物化视图主要是为了满足用户,既能对原始明细数据的任意维度分析,也能快速的对固定维度进行分析查询,在统一视角下对明细、聚合数据进行分析。
用户查询时,Palo会根据当前查询的语句去自动选择一个最优的物化视图,从物化视图中读取数据并计算。如果发生数据导入或删除,物化视图会自动更新,保证原始表和物化视图表的数据一致性。
Palo支持两层的数据划分。
第一层是 Partition,支持 Range 和 List 的划分方式。
第二层是 Bucket分桶,将数据通过Hash进行水平划分,数据分片Tablet均匀在集群中打散。
数据导入
Palo提供多种数据导入方案,可以针对不同的数据源进行选择,同时在数据导入过程中提供原子性保证。不论是使用 Broker Load 进行批量导入,还是使用 INSERT 语句进行单条导入,都是一个完整的事务操作。导入事务可以保证一批次内的数据原子生效,不会出现部分数据写入的情况。
同时,一个导入作业都会有一个 Label。这个 Label 是在一个数据库(Database)下唯一的,用于唯一标识一个导入作业。Label 可以由用户指定,部分导入功能也会由系统自动生成。
Label 是用于保证对应的导入作业,仅能成功导入一次。一个被成功导入的 Label,再次使用时,会被拒绝并报错 Label already used。通过这个机制,可以在 测做到 At-Most-Once 语义。如果结合上游系统的 At-Least-Once 语义,则可以实现导入数据的 Exactly-Once 语义。
用户分析
Palo支持标准SQL,例如单表聚合、排序、过滤以及多表Join、子查询等都支持,并且SQL语法向MySQL兼容,无额外学习成本。
Adhoc 这类高吞吐的即席查询和库内 ETL 场景也是 Palo 的强项。
Palo能够支持复杂 SQL 语法,包括窗口函数、Grouping Set 等高级语法功能,同时还可以通过 UDF 或 UDAF 来自定义拓展 Palo 的功能。
高并发场景也是Palo的优势。Palo是少有的能够支持高并发现在服务场景的OLAP系统,单节点可以支持上千QPS的查询请求。
高并发的支持得益于 Palo 的分区分桶裁剪功能。利用查询条件,Palo可以将查询固定到极少数分片上,从而显著降低单个查询对系统资源的消耗,提升集群整体的并发查询能力。
Palo还支持 SQL 级别和 Partition 级别的 Cache。其中 SQL Cache 以 SQL 语句的 Hash 值作为 Key,直接缓存 SQL 结果,非常适合更新频率不高,但是查询非常频繁的场景。
而 Partition 级别的 Cache,会智能的将 SQL 结果中不同分区的结果数据缓存起来,之后的查询,可以利用已缓存分区的数据加上新分区实时查询的数据得到最终的结果,从而降低重复数据的实时查询需求,减少对系统资源的消耗。
在用户行为分析场景,Palo支持BitMap数据类型。可以通过Bitmap进行快速分析,同时Palo内置了很多 Bitmap 相关的函数,用于计算画像、漏斗、留存等。
在Palo的最新版本中还增加了多租户和资源隔离的特性。
Palo不仅可以支持集群内节点级别的资源组划分,还可以针对单个查询的资源限制。
维护升级
作为一款分布式系统,Palo的升级方式却极其简单,只需要替换二进制程序,滚动重启集群即可。
在设计上,Palo完全向前兼容,所以也可以通过灰度升级的方式进行新版本的验证和测试。而 Palo本身的一些失败重试和故障路由,也极大程度的降低了在升级过程中对业务的影响。
同时Palo自身的分布式管理框架,可以自动的管理数据副本的分布、修复和均衡。比如对于副本损坏的情况,Palo会自动感知并进行修复。
而对于节点扩容,仅需一条SQL命令即可完成,Palo会自动进行数据分片的均衡,整个过程完全不影响系统服务,无需运维人员进行任何额外的操作。
安全稳定的云上托管服务
除此之外还充分利用了云平台优势,例如按需取用的海量资源、更加可控的资源管理等,结合百度智能云增加了许多云上特性。包括功能丰富的云上管控平台、基于对象存储BOS的冷热数据分离架构以及高效易用的企业级生态组件。
以上是老师的全部分享内容,有问题欢迎在评论区提出。