这是我参与「第四届青训营」笔记创作活动的第13天
大数据作业的简化模型
- 从存储服务读取数据(决定性能的关键因素)
- 计算引擎解析和计算数据
- 结果呈现
列存vs行存
数据格式层
在计算层和存储层之间还有一层,可称为数据格式层,其定义了存储层文件内部的组织格式,计算引擎通过格式层的支持来读写文件
行存
- 每行的数据在文件中是连续存储的
- 典型系统:关系型数据库、Key-value数据库
列存
- 每列的数据在文件中是连续存储的
- 典型系统:大数据分析系统(SQL-on-Hadoop,数据湖分析)、数据仓库(ClickHouse等)
行存列存总结
行存储适用于OLTP,列存储适用于OLAP
列存格式中常见的编码和压缩算法
编码
- plain:直接存储原始数据
- RLE(run length encoding):适用于列基数不大,但重复值较多的场景 如:
- 字典编码: 相当于是算法题中的:下标代表出现次数,元素为数据,然后用RLE编码
如图:
- 实际开发中:
- 默认场景下parquet-mr会自动根据数据特征选择
- 业务自定义(调库):org.apache.parquet.column.values.factory.ValuesWriteFactory
压缩
三种压缩算法比较
建议选择snappy(压缩速度快)和2016年后兴起的兼具速度和压缩比的zstd (笔者注:印象最深刻的一点是相比之下gzip是真不行)
Parquet和ORC的原理和区别
Parquet出自Spark,ORC出自Hive。
整体上Spark比Hive更有优势,从这方面来说Parquet可能更好。
Parquet:大数据分析领域使用最广的列存格式(Spark推荐存储格式)
实际代码编写:
- Hive table:
- load data using SparkSQL
- 上述两者区别:spark生成的文件有.parquet后缀,hive的没有
- parquet与text的格式编码:
parquet可将数据压缩到text下的1/3左右
- 一个很好用的工具:parquet-cli
Dremel数据模型
- 代码展示
- 对应的抽象图
- 表格可视化形式
嵌套类型只保存叶子结点数据
深入Dremel数据模型
r:repetiton level:该字段在field path上第几个重复字段出现
d:definition level:记录在field path上有多少个字段是可以不存在而实际出现的
re-assembly
数据布局
- 示意图(来源官网)
- 一些详细介绍
索引(index)
和传统的数据库相比,索引支持非常简陋
- Min-Max Index
- 对于列基数较大或非排序列的过滤,minmax难发挥作用,这时可以引入 bloom filter
- Column Index
- Offset Index
排序
类似于聚集索引的概念,帮助过滤掉无关的RowGroup或Page(对少量数据seek很有帮助)
过滤下推
集成Spark--向量化读(主流大数据分析引擎的标准实践)
Spark以Batch的方式从Parquet读取数据,下推的逻辑也会适配Batch方式
ORC(出自Hive项目)
数据模型
- Parquet只给叶子结点创建column,这个是都有。
- 差别还体现在对 嵌套和集合类型的支持上
- 可选和重复字段依赖父节点信息来重新编译数据
数据布局
- Rooter+Stripe+Column+Page(Row Group)结构
- 编码、压缩、索引支持上与p几乎一致
- ACID特性方面:
- 支持Hive事务实现
- 类似数据湖三剑客
- 基于Base+Delta+Compaction
市场产品介绍:AliORC(ORC的深度定制版)
- 索引增强:
- 支持集群索引,便于更快查找主键
- 支持位映射,便于更快过滤
- 小列聚合:重排Chunk
- 异步预取
Parquet与OCR的对比
- 原理层面:最大差别在于对嵌套类型和复杂类型的处理上
- P的算法复杂很多,CPU开销更大;O算法简单,但要读取更多数据
- 具体业务具体分析
列存演进趋势
数仓中的列存
- 湖仓一体的大趋势
- ClickHouse的MergeTree引擎也是基于列存构建的;默认情况下按照Column拆分;支持更加丰富的索引
存储侧下推
- 更多下推工作下沉到存储服务侧(越接近数据,下推过滤的效率更高)
- 挑战:存储侧感知Schema;计算生态的兼容和集成