我正在学习使用python和pyarrow制作的实木复合地板文件。镶木地板在压缩和最小化磁盘空间方面表现出色。我的数据集是190MB的csv文件,当另存为snappy
压缩的实木复合地板文件时,最终成为单个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
当我按日期进行分区(超过300个唯一值)时,分区文件的总大小为61MB。每个文件的大小为168.2kB
。
当我按性别分区(2个唯一值)时,分区的文件总共只有3MB。
我想知道镶木地板是否有最小文件大小,以便合并许多小文件会占用更大的磁盘空间?
我的环境:
- OS: Ubuntu 18.04
- Language: Python
- Library: pyarrow, pandas
我的数据集来源:
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
我的代码另存为实木复合地板文件:
# 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)
我的代码另存为已分区实木复合地板文件:
# 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())
答案 0 :(得分:2)
没有最小文件大小,但是存在存储页脚的开销,并且浪费了通过编码和压缩进行优化的机会。各种编码和压缩都基于这样的想法,即数据具有一定程度的自相似性,可以通过参考较早的相似事件来加以利用。当您将数据拆分为多个文件时,每个文件都需要一个单独的“初始数据点”,连续的文件可以引用该文件,因此磁盘使用率上升。 (请注意,此措词有很大的简化,以避免必须专门采用各种节省空间的技术,但是请参见this answer的一些示例。)
对Parquet文件的大小可能产生巨大影响的另一件事是插入数据的顺序。排序的列可以比随机排序的列更有效地存储。通过对数据进行分区,您可能会无意间更改其排序顺序。另一种可能性是,您可以根据数据的排序属性对数据进行分区,这在将数据存储在单个文件中时可以节省大量空间,并且通过将数据拆分为多个文件而失去了这种机会。最后,您必须记住,Parquet并不是针对存储几千字节的数据而优化的,而是针对几兆字节或几千兆字节(在一个文件中)或几PB的字节(在多个文件中)进行存储的。
如果您想检查数据如何存储在Parquet文件中,则Parquet的Java实现包括parquet-tools
实用程序,提供了几个命令。有关构建和入门的信息,请参见其documentation page。各个命令的更详细说明由parquet-tools
自己打印。您最感兴趣的命令可能是meta
和dump
。