这是我参与「第四届青训营 」 笔记创作活动的第10天
回顾
- 计算层:批式处理(Spark ),流式处理(Flink ),交互式分析(Presto)
- 存储层:HDFS,对象存储(公有云数据存储)
- 元数据管理,狭义数据湖
所有的大数据作业都可以简化为:
- 从存储层读取文件
- 计算层解析文件内容,运行各种计算算子
- 计算层输出结果,或者把结果写入存储层
1. 行存 vs 列存
数据格式层
- 数据格式层:定义了存储层文件内部的组织格式,计算引擎通过格式层的支持来读写文件
- 严格意义上,并不是一个独立的层级,而是运行在计算层的一个Library
分层视角下的数据形态
- 存储层:File,Blocks
- 格式层:File 内部的数据布局 (Layout + Schema)
- 计算引擎:Rows + Columns
OLTP vs OLAP
- OLTP 和 OLAP 作为数据查询和分析领域两个典型的系统类型,具有不同的业务特征,适配不同的业务场景
OLTP——行存
- 每一行 (Row) 的数据在文件的数据空间里连续存放的
- 读取整行的效率比较高,一次顺序 IO 即可
- 典型应用:MySQL、Oracle、RocksDB
OLAP——列存
- 每一列 (Column) 的数据在文件的数据空间里连续存放的
- 同列的数据类型一致,压缩编码的效率更好
- 典型系统:Hive、Spark,数据湖
总结
- 格式层定义了数据的布局,连接计算引擎和存储服务
- OLTP和OLAP场景使用数据存储格式不同,业务场景决定技术实现。OLTP——行存、OLAP——列存
2. Parquet 详解
- 大数据分析领域使用最广泛的列存格式
数据模型
基于Dremel,Protocol Buffer 定义;支持可选和重复字段、嵌套类型。
文件布局
Footer+RowGroup+ColumnChunk+Page
数据编码Encodeing
page粒度,Plain/RLE、Dictionary
-
Run Length Encoding (RLE):适用于列基数不大,重复值较多的场景,例如:Boolean、枚举、固定的选项等
-
Bit-Pack Encoding: 对于 32位或者64位的整型数而言,并不需要完整的 4B 或者 8B 去存储,高位的零在存储时可以省略掉。适用于最大值非常明确的情况下。
- 一般配合 RLE 一起使用
-
Dictionary Encoding:适用于列基数 (Column Cardinality) 不大的字符串类型数据存储;
- 构造字典表,用字典中的 Index 替换真实数据
- 替换后的数据可以使用 RLE + Bit-Pack 编码存储
压缩Compression
-
发生时机:Page完成Encoding之后进行压缩
-
多种压缩算法:
- snappy: 压缩速度快,压缩比不高,适用于热数据
- gzip:压缩速度慢,压缩比高,适用于冷数据
- zstd:新引入的压缩算法,压缩比和 gzip 差不多,而且压缩速度略低于 Snappy
-
建议选择 snappy 或者 zstd,根据业务数据类型充分测试压缩效果,以及对查询性能的影响
索引index和排序Ordering
- 和传统的数据库相比,索引支持非常简陋。主要依赖 Min-Max Index 和 排序 来加速查找。
bloom filter索引
- 使用场景:对于列基数比较大的场景,或者非排序列的过滤,Min-Max Index 很难发挥作用
排序Ordering
- 类似聚集索引的概念
过滤下推Predicate PushDown
- ParquetFileFormat 向量读
- Dremel数据模型:Repetition Level
3. ORC
数据模型
基于Dremel
文件布局
- 类似 Parquet,Rooter+Stripe+Column+Page
- Encoding / Compression / Index 支持上和 Parquet 几乎一致
ACID
- 支持 Hive Transactions 实现,目前只有 Hive 本身集成
- 类似 Delta Lake / Hudi / Iceberg
- 基于 Base + Delta + Compaction 的设计
AliORC
-
索引增强,支持Clusterd Index,更快的主键查找;
-
支持 Bitmap Index,更快的过滤
- Roaring Bitmap
-
小列聚合,减少小 IO;重排 ColumnChunk
-
异步预取优化,计算逻辑和数据读取并行化
Parquet vs ORC 对比
-
原理:最大的差别就是对于 NestedType 和复杂类型处理上
-
算法:
- Parquet 的算法上要复杂很多,带来的 CPU 的开销比 ORC 要略大
- ORC 的算法上相对简单,但是要读取更多的数据
4.列存演进
- 在ClickHouse数仓中的MergeTree引擎也是基于列存构建的,支持更丰富的索引方式
- 存储侧下推,越接近数据,下推过滤的效率越高
- Column Family支持,只更新需要修改的列