Python创建Parquet文件的最常见方法似乎是首先创建一个熊猫数据帧,然后使用pyarrow将表写入parquet。我担心这可能会对内存使用造成过度负担——因为它需要至少一个数据集的完整副本存储在内存中才能创建熊猫数据帧。
我想知道是否由于列式压缩要求而需要将整个数据集加载到内存中,或者是否有更高效和基于流的方法。在我的例子中,我会以流式方式接收记录。对于类似的csv输出过程,我们以1000为批次将行写入磁盘,因此需要在内存中保存的行数永远不会达到完整数据集的大小。
我应该…?:
想法?建议?
使用一些流式友好的方式在我们收到它们时一次写入1000行左右,从而最大限度地减少整个过程中的总时间点内存消耗。
你可以做到这一点。
(我没有看到任何关于如何做到这一点的留档,我不确定这是否是拼花地板的一个选择。)
至少现在https://arrow.apache.org/docs/python/generated/pyarrow.parquet.ParquetWriter.html有一些关于如何做到这一点的留档-特别是write_batch
函数
这是一个示例,尽管它必须根据数据源进行一些调整。例如,如果if已经出现“分块”,或者如果模式必须从数据中推断出来,而不是像这里那样硬编码。
该示例还通过Pandas进行,主要是因为它是一种从行转换为列以创建每个RecordBatch的便捷方式,但还有其他不需要熊猫的创建每个RecordBatch的方法。
import itertools
import pandas as pd
import pyarrow as pa
import pyarrow.parquet as pq
# Any iterable that yields rows as tuples
def get_rows():
for i in range(0, 10000):
yield (1, 2)
# Chunk the rows into arrow batches
def get_batches(rows_iterable, chunk_size, schema):
rows_it = iter(rows_iterable)
while True:
batch = pa.RecordBatch.from_pandas(
pd.DataFrame(itertools.islice(rows_it, chunk_size), columns=schema.names),
schema=schema, preserve_index=False,
)
if not batch:
break
yield batch
# Could be inferred from data, but note that the schema has to be
# known when creating the ParquetWriter object
schema = pa.schema([
('a', pa.int32()),
('b', pa.int32()),
])
rows = get_rows()
batches = get_batches(rows, chunk_size=1000, schema=schema)
# Write the batches
with pq.ParquetWriter('example.parquet', schema=schema) as writer:
for batch in batches:
writer.write_batch(batch)
您希望在Parquet中使用行组。请参阅此处了解它们的解释,但简短的版本是列式数据仅限于多行的块,每个块都可以单独附加到文件中。您可以使用PyArrow为传入数据流实现这一点。