高性能列式存储|青训营笔记

125 阅读2分钟

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

数据形态

  • 存储层:File,Blocks
  • 格式层:File内部的数据格式(Schema+Layout)
  • 计算引擎:Rows,Columns image.png

OLTP 行存

每一行的数据在文件上是连续存储的

读取整行数据效率高,单次IO顺序读即可

典型

  • 关系型数据库:MySQL,Oracle等
  • Key-Value数据库

OLAP 列存

每一列的数据在文件上是连续存储的

读取整列数据效率高;同列数据类型一致,压缩编码效率更高

  • 大数据分析系统: SQL-on-Hadoop , 数据湖分析
  • 数据仓库: ClickHouse,Greenplum ,阿里云MaxCompute

Parquet原理

数据布局

  • RowGroup:每一个行组包含一定数量或者固定大小的行的集合
  • ColumnChunk: RowGroup中按照列切分成多个ColumnChunk
  • Page: ColumnChunk内部继续切分成Page,一般建议8KB大小。压缩和编码的基本单元根据保存的数据类型分为: Data Page,Dictionary Page,Index Page
  • Footer保存文件的元信息
  • Schema
  • Config
  • Metadata
    • RowGroup Meta
      • Column Meta

编码

  • Plain,直接存储原始数据
  • Run Length Encoding,列基数不大,重复值较多的场景如:bool类型,枚举,固定的选项等。Bit-Pack Encoding :配合RLE编码使用让整形数字存储的更加紧凑。
  • 字典编码 Dictionary Encoding,构建字典表,写入Dictionary Page,用index替代数据,再用RLE。

压缩

先编码,再压缩

  • snappy:压缩速度快,压缩比不高,适用于热数据
  • gzip:压缩速度慢,压缩比高,适用于冷数据
  • zstd:压缩速度比肩snappy,压缩比接近gzip

索引

  • Min-Max Index:记录page内部的最值
  • Column Index:Footer中的Column Metadata包含Columnchunk全部page的Min-Max Value
  • Offset Index:记录Page在文件中的Offset和Page的Row Range

列基数较大或非排序列的过滤,Min-Max Index难以发挥作用 Bloom Filter

  • 引入Bloom Filter加速过滤匹配判定
  • 每个ColumnChunk的头部保存Bloom Filter数据
  • Footer记录Bloom Filter的page offset

过滤下推

  • parquet-mr库实现,实现高效的过滤机制
  • 引擎侧传入Filter Expression
  • parquet-mr转换成具体Column的条件匹配
  • 查询Footer里的Column Index ,定位到具体的行号
  • 返回有效的数据给引|擎侧

ORC

数据布局

与parquet相似;Rooter+Stripe+Column+Page(Row Group)结构

ACID

支持Hive Transactions实现,目前只有Hive集成

基于Base+Delta+Compaction的设计

AliORC

索引增强

支持Clusterd Index更快地进行主键查找 支持Bitmap Index更快地过滤;Roaring Bitmap;较稀疏的情况

小列聚合

减少小IO,将较小的列放置到一起

异步预取

将计算逻辑和数据读取并行化