1. Parquet文件格式选用thrift完成文件元数据的序列化和反序列化。在parquet-format项目的thrift目录下,文件parquet.thrift详细定义了parquet文件的元数据类型。下面这张图较好的描述了parquet元数据的数据结构。
2. parquet文件的列块层级之上的元数据信息,都封装在FileMetaData中,写在parquet文件的最后。最顶层的FileMetaData对象中,version字段记录parquet文件的版本,schema字段记录parquet文件的schema,num_rows字段记录文件包含的字段条数,row_groups记录文件包含的行组信息,上面4个字段是文件元数据对象必须设置的元素,另外还有两个可选填的字段:key_value_metadata记录额外的键值对信息,created_by记录文件创建者信息。由于Thrift不支持嵌套,所以树形数据结构的schema,按照深度优先的顺序保存schema的节点。第二层级的元数据结构是RowGroup,代表parquet文件的一个行组,其中total_byte_size记录整个行组占用空间大小,num_rows记录行组中记录条数,columns记录该行组中各个列块的信息。各个行组在FileMetaData元数据中的顺序,和其写入文件的顺序相同。第三层级的数据结构便是ColumnChunk和ColumnMetaData,ColumnChunk记录该列块在文件中的偏移量。ColumnMetaData记录该列块中,该列的数据类型、编码方式、压缩方式、列名、记录条数、占用空间大小、起始数据页(Page)在文件中的偏移量。
PageHeader是每一个Page的元数据,在写入每一个Page数据之前,该Page对应的PageHeader被写入文件中。parquet支持index page,其可以用于保存该Page内的索引信息。DictionaryPage是采用Dictionary编码时,保存该page列元素词典的Page。
3. parquet编码方式
基本数据类型默认的编码方式:BOOLEAN类型被编码成一个bit;INT32被编码成4个字节,以小端方式存储;BYTE_ARRAY类型被编码成:前四个字节为字符串长度,后面字节为字符串内容。FIX_LEN_BYTE_ARRAY直接将字符串内容编码成字节。
Page中数据字段编码方式:RLE(run length encoding)游程长度编码,例如字符串aaaaabbbbb,被编码成5a5b,该编码适用于具有大量重复元素的字段;Dictionary encoding词典编码,适用于该字段unique值数量远远小于记录条数的情况,在page中单独创建一个DictionaryPage保存字段unique值,DataPage中,只需记录该unique值在DictionaryPage中的id,Dictionary encoding通常和RLE结合使用。
4. thrift用于对象序列化
thrift提供了接口定义语言(IDL),类似于C语言中结构体struct的定义语法,使用thrift自带的代码生成工具可以将定义的struct转化成各种语言的类。生成的类可以采用thrift实现的各种传输协议序列化到输出流中,例如:TCompactProtocol、TBinaryProtocol、TJsonProtocol。
5. parquet文件版本
在parquet-1.6.0中,实现了两个版本的parquet文件编码方式,version_1.0中各字段都采用普通的编码方式(plain)。version_2.0中,若开启了词典模式(dictionary),则除boolean类型的字段外,其它所有字段默认都采用dictionary+rle+bit packing编码方式。dictionary+rle+bit packing编码的具体实现是:把一个ColumnChunk列块中该字段所有unique值保存在一个独立的Dictionary Page中,然后列块的Data Page只需使用一个int32类型的值保存该字段的值在DictionaryPage中的序号id;同时int32类型的Data Page采用bit packing编码方式,根据最大编号确定使用的位宽度bit-width,例如说:有10个unique值,则只需要使用4位(bit)保存每一个id就可以了,然后将所有的字节连接起来,连接的时候使用的是rle编码。当词典大小超过阈值(可以设置)、编码后的数据大小大于原数据普通编码大小时,该字段的编码方式将根据数据类型自动转换成另一种编码方式,例如:字符串将采用delta byte array,详细的转换可见parquet-column项目parquet.column包下的ParquetProperties类。