用pyarrow / parquet-cpp对parquet-mr生成的木地板重新分区会增加30倍的文件大小吗?

时间:2018-10-26 16:38:32

标签: pandas parquet amazon-kinesis-firehose pyarrow

使用AWS Firehose,我正在将传入记录转换为实木复合地板。在一个示例中,我有150k条相同的记录输入firehose,并且将一个30kb的镶木地板写入s3。由于firehose如何划分数据,我们在镶木地板中读取了一个辅助进程(由s3 put事件触发的lambda),并根据事件本身中的日期对其进行了重新分区。重新分区后,文件大小从30kb跃升到900kb。

检查两个实木复合地板文件-

  • 元数据不变
  • 数据不变
  • 它们都使用SNAPPY压缩
  • firehose木地板由parquet-mr创建,pyarrow生成的木地板由parquet-cpp创建
  • 由pyarrow生成的实木复合地板还有其他熊猫头

完整的重新分区过程-

import pyarrow.parquet as pq

tmp_file = f'{TMP_DIR}/{rand_string()}'
s3_client.download_file(firehose_bucket, key, tmp_file)

pq_table = pq.read_table(tmp_file)

pq.write_to_dataset(
    pq_table,
    local_partitioned_dir,
    partition_cols=['year', 'month', 'day', 'hour'],
    use_deprecated_int96_timestamps=True
)

我想尺寸会有一些变化,但是我惊讶地发现如此大的差异。根据我描述的过程,是什么导致源实木复合地板从30kb变为900kb?

1 个答案:

答案 0 :(得分:1)

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