为什么分区 parquet 文件会占用更大的磁盘空间?

add*_*ted 6 python parquet pyarrow

我正在学习使用 python 和 pyarrow 的镶木地板文件。Parquet 在压缩和最小化磁盘空间方面非常出色。snappy我的数据集是 190MB csv 文件,当保存为压缩 parquet 文件时,最终会成为单个 3MB 文件。

然而,当我将数据集保存为分区文件时,它们会导致组合大小更大(61MB)。

这是我尝试保存的示例数据集:

listing_id |     date     | gender | price
-------------------------------------------
     a     |  2019-01-01  |   M    |   100
     b     |  2019-01-02  |   M    |   100
     c     |  2019-01-03  |   F    |   200
     d     |  2019-01-04  |   F    |   200

Run Code Online (Sandbox Code Playgroud)

当我按日期(300 多个唯一值)分区时,分区文件的总大小为 61MB。每个文件都有168.2kB大小。当我按性别(2 个唯一值)分区时,分区文件的总大小仅为 3MB。

我想知道镶木地板是否有最小文件大小,这样许多小文件组合起来会消耗更大的磁盘空间?

我的环境:

- OS: Ubuntu 18.04
- Language: Python
- Library: pyarrow, pandas
Run Code Online (Sandbox Code Playgroud)

我的数据集来源:

https://www.kaggle.com/brittabettendorf/berlin-airbnb-data

# I am using calendar_summary.csv as my data from a group of datasets in that link above
Run Code Online (Sandbox Code Playgroud)

我保存为镶木地板文件的代码:

# write to dataset using parquet
df = pd.read_csv('./calendar_summary.csv')
table = pyarrow.Table.from_pandas(df)
pyarrow.parquet.write_table(table=table, where='./calendar_summary_write_table.parquet')

# parquet filesize
parquet_method1_filesize = os.path.getsize('./calendar_summary_write_table.parquet') / 1000
print('parquet_method1_filesize: %i kB' % parquet_method1_filesize)
Run Code Online (Sandbox Code Playgroud)

我的代码保存为分区镶木地板文件:

# write to dataset using parquet (partitioned)
df = pd.read_csv('./calendar_summary.csv')
table = pyarrow.Table.from_pandas(df)
pyarrow.parquet.write_to_dataset(
    table=table, 
    root_path='./calendar_summary/', 
    partition_cols=['date'])

# parquet filesize
import os
print(os.popen('du -sh ./calendar_summary/').read())
Run Code Online (Sandbox Code Playgroud)

Zol*_*tan 6

没有最小文件大小,但存储页脚会产生开销,并且会浪费通过编码和压缩进行优化的机会。各种编码和压缩都建立在数据具有一定程度的自相似性的基础上,可以通过引用早期的相似事件来利用这种自相似性。当您将数据拆分为多个文件时,每个文件都需要一个单独的“初始数据点”,以便后续文件可以引用,因此磁盘使用量会增加。(请注意,此措辞过于简单化,以避免必须专门介绍用于节省空间的各种技术,但请参阅此答案以获取一些示例。)

对 Parquet 文件大小产生巨大影响的另一件事是数据插入的顺序。排序列的存储效率比随机排序列的存储效率高得多。通过对数据进行分区,您可能会无意中更改其排序顺序。另一种可能性是,您按数据排序的属性对数据进行分区,这在存储在单个文件中时可以节省大量空间,但通过将数据拆分为多个文件,就会失去这个机会。最后,您必须记住,Parquet 并未针对存储几千字节的数据进行优化,而是针对几兆字节或千兆字节(在单个文件中)或几拍字节(在多个文件中)进行优化。

如果您想检查数据在 Parquet 文件中的存储方式,Parquet 的 Java 实现包含该parquet-tools实用程序,它提供了多个命令。有关构建和入门的信息,请参阅其文档页面。各个命令的更详细描述由其parquet-tools自身打印。您最感兴趣的命令可能是metadump