Parquet 使用不同的列编码来非常有效地存储低熵数据。例如:
- 它可以使用增量编码来仅存储值之间的差异。例如
9192631770, 9192631773, 9192631795, 9192631797
将有效地存储为9192631770, +3, +12, +2
.
- 它可以使用字典编码来简短地引用公共值。例如,
Los Angeles, Los Angeles, Los Angeles, San Francisco, San Francisco
将存储为字典0 = Los Angeles, 1 = San Francisco
和引用0, 0, 0, 1, 1
- 它可以使用游程编码来仅存储重复值的数量。例如,
Los Angeles, Los Angeles, Los Angeles
将有效地存储为Los Angeles×3
. (实际上据我所知,纯 RLE 目前仅用于布尔类型,但想法是一样的。)
- 上述的组合,特别是 RLE 和字典编码。例如,
Los Angeles, Los Angeles, Los Angeles, San Francisco, San Francisco
将存储为字典0 = Los Angeles, 1 = San Francisco
和引用0×3, 1×2
使用上面示例的 3 到 5 个值,节省的费用并不那么显着,但是您拥有的值越多,收益就越大。由于您有 150k 条相同的记录,因此收益将是巨大的,因为使用 RLE 字典编码,每个列值只需存储一次,然后标记为重复 150k 次。
但是,pyarrow 似乎没有使用这些节省空间的编码。您可以通过查看两个文件的元数据来确认这一点,使用parquet-tools meta
. 这是一个示例输出:
file schema: hive_schema
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
id: OPTIONAL INT32 R:0 D:1
name: OPTIONAL BINARY O:UTF8 R:0 D:1
row group 1: RC:61 TS:214 OFFSET:4
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
id: INT32 UNCOMPRESSED DO:0 FPO:4 SZ:107/107/1.00 VC:61 ENC:BIT_PACKED,RLE,PLAIN_DICTIONARY ST:[min: 1, max: 5, num_nulls: 0]
name: BINARY UNCOMPRESSED DO:0 FPO:111 SZ:107/107/1.00 VC:61 ENC:BIT_PACKED,RLE,PLAIN_DICTIONARY ST:[min: Los Angeles, max: San Francisco, num_nulls: 0]
编码显示为ENC:BIT_PACKED,RLE,PLAIN_DICTIONARY
。