Parquet 与 ORC:高性能列式存储 | 青训营笔记
这是我参与「第四届青训营 」笔记创作活动的第6天
-
Parquet读取流程
读取文件元数据
-
首先在 ParquetReader.build 时,读取文件尾部的 Footer,里边有整个文件的元数据,即ParquetMetadata。
-
初始化: ParquetReader.initReader()
-
过滤 RowGroup。根据 RowGroup 中的统计信息和 Filter,对文件中的所有 RowGroup 进行过滤,将不满足的 RowGroup 丢掉。
-
构造 RecordReader: InternalParquetRecordReader.checkRead()
-
读取一个 RowGroup (包含各个 Chunk 的 PageReader),将查询涉及的所有 Chunk 的字节读到内存中。
-
对每个 Chunk,将其所有 Page 构造出来,用字节数组填充,作为压缩后的 Page,并用这些压缩的 Page 和解码器构造一个 ColumnChunkPageReader。
-
根据这些 ColumnChunkPageReader 构造 RecordReader。构造了一个 RecordReaderImplementation。并且在 ColumnReaderImpl 的 checkRead() 方法里开始读 Page,解压缩 page。
-
读取一行数据
-
根据 Definition Level 和 Repetition Level 的计算方法构造出一行一行 Record 来,这一行 Record 如果为 Null,就是不满足条件,继续构造 Record。在过滤的时候一直维护一个 IncrementallyUpdatedFilterPredicate,这个谓词里记录了当前 record 是否满足条件,在 IncrementallyUpdatedFilterPredicateBuilder 里根据新的数据更新这个谓词的状态。
-
ORC文件结构
-
ORC文件以二进制方式存储,所以是不可以直接读取,ORC文件也是自解析的,它包含许多的元数据,这些元数据都是同构ProtoBuffer进行序列化的。ORC的文件结构如下图,其中涉及到如下的概念:
-
ORC文件:保存在文件系统上的普通二进制文件,一个ORC文件中可以包含多个stripe,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念。
-
文件级元数据:包括文件的描述信息Post、文件meta信息(包括整个文件的统计信息)、所有stripe的信息和文件schema信息。
-
stripe:一组行形成一个stripe,每次读取文件是以行组为单位的,一般为HDFS的块大小,保存了每一列的索引和数据。
-
stripe元数据:保存stripe的位置、每一个列的在该stripe的统计信息以及所有的stream类型和位置。
-
row group:索引的最小单位,一个stripe中包含多个row group,默认为10000个值组成。
-
stream:一个stream表示文件中一段有效的数据,包括索引和数据两类。索引stream保存每一个row group的位置和统计信息,数据stream包括多种类型的数据,具体需要哪几种是由该列类型和编码方式决定。
(待补充)