以内存高效的方式从python中的流创建Parquet文件



在Python中创建Parquet文件最常见的方法似乎是首先创建Pandas数据帧,然后使用pyarrow将表写入Parquet。我担心这可能会使内存使用过于繁重,因为它需要至少一个完整的数据集副本存储在内存中,才能创建pandas数据帧。

我想知道,由于柱状压缩要求,是否需要将整个数据集加载到内存中,或者是否有更高效的基于流的方法。就我而言,我将以流媒体方式接收这些记录。对于类似的csv输出过程,我们以1000为一批将行写入磁盘,因此需要保存在内存中的行数永远不会达到整个数据集的大小。

我应该…吗?:

  1. 只需创建一个pandas数据帧,然后将其写入镶木地板。(这意味着整个数据集需要存储在内存中,但我们将其视为必要的要求。(
  2. 使用一些流式传输友好的方式,在接收到行时一次写入1000行左右,从而最大限度地减少整个过程中的时间点内存消耗。(我没有看到任何关于如何做到这一点的文档,我甚至不确定这是否是镶木地板的选项。(
  3. 将所有内容写入CSV,然后使用一个函数智能地读取/分析CSV内容,并在事后创建压缩拼花地板。(运行时可能较慢,但内存配置文件较低,在很大的文件上失败的几率较低。(

想法?建议?

使用一些流媒体友好的方式,在接收到行时一次写入1000行左右,最大限度地减少整个过程中的时间点内存消耗。

您可以这样做。

(我没有看到任何关于如何做到这一点的文档,我甚至不确定它是否是镶木地板的选项。(

至少现在在https://arrow.apache.org/docs/python/generated/pyarrow.parquet.ParquetWriter.html关于如何做到这一点,特别是write_batch功能


这是一个例子,尽管它必须根据数据源进行一些调整。例如,如果"如果已经到来";分块的";或者如果必须从数据推断模式而不是像这里那样硬编码。

这个例子也通过Pandas,主要是因为它是一种从行转换为列以创建每个RecordBatch的方便方法,但也有其他创建每个Record批次的方法不需要Pandas。

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为传入数据流实现此功能。

相关内容

  • 没有找到相关文章

最新更新