关于 Parquet Encodings 相关的一些记录
最近在看 Parquet 支持的各种编码的详细的实现,但是发现官方文档中对于一些细节的描述并不是很清楚,在此结合源码记录一下。
- 官方文档:https://github.com/apache/parquet-format/blob/master/Encodings.md
- 参考源码:https://github.com/apache/arrow-rs/tree/master/parquet/src/encodings
PLAIN
如何编码变长字符串(BYTE_ARRAY)
每一个字符串都由 <len><data>
组成,其中 <len>
为定长的 u32
类型。直接上代码:
1 | impl ParquetValueType for super::ByteArray { |
P.S. 对于定长字符串(FIXED_LEN_BYTE_ARRAY),不需要把 <len>
一起编码,只需要编码 <data>
。
默认情况下,字符串不会使用这样的编码,默认是采用 DELTA_LENGTH_BYTE_ARRAY 方式。
PLAIN_DICTIONARY / RLE_DICTIONARY
没什么好补充的。
RLE (RLE / Bit-Packing Hybrid)
Bit width 如何选择
通过上层传入,Encoder 本身不会决定位宽。上层使用能包含当前所有数字的最小 bit width 作为 encoder 采用的 bit width。
用 LevelsEncoder 为例,在编解码过程中,我们都能够获取到 max_level
,再通过这个值换算出最少需要的 bit 个数即可。
如何选择采用 RLE 还是 Bit-Packing 编码
编码时以 8 个 value 为一组,如果 8 个全部为同样的 value,则采用 RLE,并一直编码到不同的 value 出现为止;如果 8 个 value 中有不同的 value,则采用 Bit-Packing 编码。
即使 8 个 value 中只有第一个 value 不同,后面 7 个 value 都相同,也会采用 Bit-Packing 编码。如果下一个 value 和前面的 7 个 value 相同,但前面 8 个 value 已经作为一组数据进行了 Bit-Packing 编码,
这个后续的 value 也无法和前面的 value 一起被按照 RLE 编码了,只能作为新的一组数据重新选择编码方式。
举个例子,表示方式为:编码方式(值个数)
1 | 01111111 111111111111 00000001 10101010 |
结束编码时 buffer 内不满 8 个 value 如何选择编码方式
如果 buffer 中的数据原不相同,则采用 RLE 编码;否则使用 0 padding 到 8 个之后使用 Bit-Packing 编码。
BIT_PACKED
没什么好补充的。
DELTA_BINARY_PACKED
如何确定 block size
(一个 block 中包含的记录数), miniblock size
(一个 miniblock 包含的记录数), number of minibocks in a block
(一个 block 中 miniblock 的个数):
直接上代码。
1 | let mini_block_size = match T::T::PHYSICAL_TYPE { |
DELTA_LENGTH_BYTE_ARRAY
没什么好补充的。
DELTA_BYTE_ARRAY
没什么好补充的。
BYTE_STREAM_SPLIT
没什么好补充的。