这是我参与「第四届青训营 」笔记创作活动的第19天
本次笔记重点内容
- 列式存储和行式存储
- Parquet 列存格式的原理
- ORC 列存格式的原理以及和Parquet 的对比
- 列存格式的演进
数据格式层
- 计算层:各种计算引擎,Rows+Columns
- 存储层:承载数据的持久化存储,File/Blocks
- 格式层:定义了存储层文件内部组织格式,高效读取文件,连接计算引擎和存储服务,Layout+Schema
OLTP && OLAP
OLTP——行式存储格式
每行数据在文件上是连续存储的,读取整行数据效率高——单次IO顺序读即可
应用场景:在典型的 OLTP 型的分析和存储系统中应用广泛,例如MySQL、Oracle等
OLAP——列式存储格式
每列数据在文件上是连续存储的,读取整列数据效率高,同列的数据类型一致
应用场景:在典型的 OLAP 型分析和存储系统中广泛应用,例如Hive、Spark、数据湖分析等
Parquet
大数据分析领域使用最广的列式存储,Spark广泛应用的存储格式
Parquet && 普通文本格式
Parquet存储格式小,Text大很多
Parquet数据模型
依据 Dremel 数据模型
构建语法树,嵌套类型只保存叶子节点数据格式。
数据文件布局
- RowGroup: 每一个行组包含一定数量或者固定大小的行的集合(在 HDFS 上,RowGroup 大小建议配置成 HDFS Block 大小)
- ColumnChunk: RowGroup 中按照列切分成多个 ColumnChunk
- Page:ColumnChunk内部继续切分成 Page,Page 是压缩和编码的基本单元。根据保存的数据类型,Page 可以分为:Data Page、Dictionary Page、Index Page
- Footer 保存文件的元信息
- Schema
- Config
- Metadata
数据编码
- Plain直接存储原始数据
- Run Length Encoding(RLE)
- Dictionary Encoding 字典编码
构造字典表,用字典中的 Index 替换真实数据,替换后的数据可以使用 RLE + Bit-Pack 编码存储
压缩方式
- snappy: 压缩速度快,压缩比不高,适用于热数据
- gzip:压缩速度慢,压缩比高,适用于冷数据
- zstd:新引入的压缩算法,压缩比和 gzip 差不多,压缩速度略低于 Snappy
索引 Index
和传统的数据库相比,索引支持非常简陋,主要依赖 Min-Max Index 和排序来加速查找。
- Page:记录 Column 的 min_value 和 max_value
- Footer 里的 Column Metadata 包含 ColumnChunk 的全部 Page 的 Min-Max Value
Bloom Filter 过滤器
对于列基数比较大的场景,或者非排序列的过滤,引入 Bloom Filter 加速过滤匹配判定
排序 Ordering
聚集索引的概念,帮助更好的过滤掉无关的RowGroup或Page
过滤下推Predicate PushDown
高效过滤机制,在格式层过滤掉大多数不相关的数据,减少真实的读取数据量
Spark集成——向量化读
向量化读是主流大数据引擎的标准实践,极大提升了查询性能。Spark以Batch的方式从 Parquet 读取数据,下推的逻辑也会适配 Batch 的方式
ORC
大数据分析领域使用最广的列存格式之一,出自Hive项目
数据模型
ORC 会给包括根节点在内的中间节点都创建一个 Column,嵌套类型或者集合类型支持和 Parquet 差别较大,optional 和 repeated 字段依赖父节点记录额外信息来重新 Assembly 数据
数据布局
类似Parquet,Encoding / Compression / Index 支持上和 Parquet 几乎一致
AliORC
索引增强
支持 Clusterd Index,更快的主键查找;支持 Bitmap Index,更快的过滤
小列聚合——减少小IO
重排Chunk——把小的列放到一起,方便读取
异步预取
在计算引擎处理已经读到的数据的时候,异步去预取下一批次数据,计算逻辑和数据读取并行化
Parquet VS ORC
- 从原理层面,最大的差别就是对于 NestedType 和复杂类型处理上
- Parquet 的算法上要复杂很多,带来的 CPU 的开销比 ORC 要略大
- 在Spark场景下Parquet工作更好,Hive场景下ORC更好。Spark比Hive更有优势,Parquet可能是更好的选择
列存演进
数仓中的列存
默认情况下列按照 Column 拆分成单独的文件,也支持单个文件形式;支持更加丰富的索引;湖仓一体大趋势
存储侧下推- 更多的下推工作下沉到存储服务侧
更多下推工作下沉到存储服务侧;越接近数据,下推过滤的效率越高
Column Family 支持
Hudi 数据湖场景下,支持部分列的快速更新,把需要更新的列拆成独立的 Column Family,Update 操作实际效果有 10+ 倍的提升