Parquet 与 ORC:高性能列式存储 | 青训营笔记

429 阅读5分钟

image.png

这是我参与「第四届青训营 」笔记创作活动的的第14天

学习目标 1660205416607.png 课程目录

01.列存vs行存

1.1 两种数据查询分析场景:OLTP vs OLAP

image.png

1.2 OLAP:列式存储格式(列存)

  • 特点:
    ·每列的数据在文件上是连续存储的
    ·读取整列的效率较高
    ·同列的数据类型一致,压缩编码的效率更好
  • 典型系统
    ·大数据分析系统:SQL-on-Hadoop,数据湖分析
    ·数据仓库:ClickHouse , Greenplum,阿里云MaxCompute

image.png

1.3 OLTP:行式存储格式(行存)

  • 特点:
    ·每行的数据在文件上是连续存储的
    ·读取整行数据效率高,单次IO顺序读即可
  • 典型系统
    ·关系型数据库:MySQL ,Oracle ...
    .Key-Value数据库
    image.png

02.Parquet原理详解

Spark推荐的存储格式,大数据分析领域使用最广的列示存储格式

2.1 Parquet简介

2.1.1 Parquet in Action-DDL

2.1.2 Parquet in Action-Spark

1.Spark生成的文件会有.Parquet后缀
2.Hive生成的文件没有后缀

2.1.3 Parquet in Action-Parquet vs. Text Format

Parquet 存储格式小(高效的压缩和编码模式,虽然做了压缩,性能上的收益较好) 1660213228553.png Text 存储格式大 1660213257132.png

2.1.4 Parquet in Action-Spark

2.2 Dremel数据模型

1660209446818.png

2.2.1 Dremel数据模型-Continued

嵌套类型只保存叶子节点的数据 image.png

2.2数据布局

image.png

2.3 编码Encoding

Run Length Encoding (RLE)∶适用于列基数不大,重复值较多的场景,例如:Boolean、枚举、固定的选项等。 Bit-Pack Encoding :配合RLE编码使用,让整形数字存储的更加紧凑

1660209997517.png 字典编码 Dictionary Encoding :适用于列基数不大的场景,构造字典表,写入到Dictionary Page;把数据用字典Index替换,然后用RLE编码

2.4 压缩

Page 完成 Encoding以后,进行压缩。
支持多种压缩算达
snappy: 压缩速度快,压缩比不高,适用于热数据
gzip:压缩速度慢,压缩比高,适用于冷数据
zstd:新引入的压缩算法,压缩比和gzip差不多,而且压缩速度比肩Snappy
建议选择snappy或者zstd,根据业务数据类型充分测试压缩效果,以及对查询性能的影响

image.png

2.5 索引

和传统的数据库相比较,索引支持非常简陋

2.6 排序

  • 类似于聚集索引的概念
  • 排序帮助更好的过滤掉无关的RowGroup或者Page ·对于少量数据Seek很有帮助
  • Parquet Format支持SortingColumns
  • Parquet Library目前没有支持
  • 依赖业务侧根据查询特征去保证顺序

2.7过滤下推

image.png

2.8 Spark集成-向量化读

  • ParquetFileFormat类
  • 向量化读开关:spark.sql.parquet.enableVectorizedReader
  • 向量化读是主流大数据分析引擎的标准实践,可以极大的提升查询性能
  • Spark以Batch的方式从Parquet读取数据,下推的逻辑也会适配Batch的方式

向量化读和过滤下推spark3.2以后的版本有比较好的结合

2.9 深入DREMEL数据模型--Repetition Level

  • Repetition Level:该字段在Field Path 上第几个重复字段上出现
  • 0:标识新的Record
  • Name.Language.Code 为例,Name是第1个重复字段,Language是第2个重复字段

2.9.1 深入Dremel数据模型- Definition Level

  • Definition Level:用来记录在fieldpath中,有多少个字段是可以不存在(optional/repeated)而实际出现的
  • Name.Language.Code为例,Name和Language 都是可以不存在的
  • 第一个 NULL字段,D是1,说明Name是存在的,但是Language是不存在的,保留原有的信息

image.png

2.9.2 深入Dremel数据模型一Re-Assembly

·根据全部或者部分列数据,重新构造Record
·构造FSM状态机
·根据同一个Column下一个记录的RepetionLevel决定继续读的列

image.png

image.png

03.ORC详解和对比

3.1 ORC简介

大数据分析领域使用最广的列式格式之一、出自于Hive项目

3.2 数据模型

image.png

NestedType的不同实现对于IO模型有什么影响?

3.3 数据布局

  • 类似Parquet
  • Rooter + Stripe + Column + Page (Row Group)结构
  • Encoding / Compression / lndex支持上和 Parquet几乎一致

3.4 ACID特性简介

  • 支持Hive Transactions 实现,目前只有Hive 本身集成
  • 类似 Delta Lake / Hudi / lceberg
  • 基于Base + Delta + Compaction的设计

3.5 AliORC

  • ORC在阿里云计算平台被广泛应用,主流产品MaxCompute +交互式分析Hologres 的最新版本都支持ORC格式
  • AliORC是对ORC的深度定制版

3.5.1 AliORC 索引增强

  • 支持Clusterd Index,更快的主键查找
  • 支持 Bitmap Index,更快的过滤
  • Roaring Bitmap

image.png image.png MaxCompute

3.5.2 AliORC-小列聚合

  • 小列聚合,减小IO 重排Chunk

3.5.3 AliORC-异步预取

image.png

3.5.4 思考

小列聚合什么场景下效果比较好?
异步预取什么场景下效果比较好?
如何基于Parquet实现同样的优化?

3.6 Parquet与ORC的对比

  • 从原理层面,最大的差别就是对于NestedType和复杂类型处理上。
  • Parquet的算法上要复杂很多,带来的CPU的开销比ORC要略大
  • ORC的算法上相对简单,但是要读取更多的数据
  • 因此,这个差异的对业务效果的影响,很难做一个定性的判定,更多的时候还是要取决于实 际的业务场景

3.6.1 性能对比

image.png

3.6.2 选择对比

最新的版本来看,Parquet 和ORC在性能上没有非常明显的差距和短板
√性能上很多情况下依赖于数据集和测试环境,不能迷信 Benchmark结果
√根据实际业务做充分的测试调优
√Spark生态下Parquet比较普遍
√Hive生态下ORC有原生支持
整体上,Spark 比 Hive更加有优势,所以大部分情况下,Parquet可能是个更好的选择。

04.列存演进

4.1 数仓中的列存

ClickHouse的MergeTree引擎也是基于列存构建的
默认情况下列按照Column拆分
支持更加丰富的索引
湖仓一体的大趋势

4.2 存储侧下推

4.3 Column Family支持