У меня есть 12 файлов паркета в каталоге с соответствующими столбцами, которые я пытаюсь записать в секционированный объект с помощью Polars и PyArrow. Я перебираю каждый файл в каталоге и читаю его как LazyFrame. Затем я перебираю список DataFrames и записываю их в секционированный объект. Предполагаемый размер каждого DataFrame составляет ~ 1 ГБ, а все объединенные DataFrame ~ 10 ГБ. Процесс использует ~15 ГБ ОЗУ и завершается менее чем за час.
Я попытался сделать это с помощью следующего кода:
all_lazyframes: list[pl.LazyFrame] = []
for file in glob.glob(input_path):
lazyframe: pl.LazyFrame = pl.scan_parquet(file)
all_lazyframes.append(lazyframe)
dataframes: list[pl.DataFrame] = pl.collect_all(all_lazyframes)
for output in dataframes:
output.write_parquet(
output_path,
use_pyarrow=True,
pyarrow_options = {"partition_cols": ["part"]},
)
Результирующий секционированный объект имеет следующую структуру:
partitioned_object/
part=a/
data0.parquet
data1.parquet
...
part=b/
data0.parquet
data1.parquet
...
Размер этого объекта составляет ~250 ГБ. Мой вопрос: почему разделенный объект такой большой, если общий размер входных данных составляет всего ~ 10 ГБ? Есть ли более эффективный способ добиться этого?
В каждом разделе по 13 файлов паркета, всего 26.
Итак, вы переходите от 12 файлов, занимающих в общей сложности 10 ГБ, к 26 файлам, занимающим в общей сложности 250 ГБ? Поначалу я предполагал, что у вас так много файлов, что эффективность сжатия теряется, и вам мешает накопление метаданных. Поскольку вы получаете файлы чуть более чем в два раза больше, я бы не подумал, что это объясняет увеличение размера в 25 раз, если только я чего-то не упускаю. Вы можете сравнить файлы с этим arrow.apache.org/docs/python/generated/…
ВВЕДЕНИЕ ПАРКЕТА МЕТАДАТЫ: <PYARROW._PARQUET.FILEMETADATA Объект по адресу 0x108892200> Create_by: Parquet-cpp-arrow версия 10.0.1 num_columns: 14 num_row Объект _parquet.FileMetaData по адресу 0x108892200> создано: parquet-cpp-arrow версия 13.0.0 num_columns: 13 num_rows: 5000000 num_row_groups: 306 format_version: 2.6 serialized_size: 297097






Я решил эту проблему, указав размер строк для каждой группы в функции ds.write_dataset(). Метод поляр в настоящее время занимает больше времени, и вы не можете указать количество строк в группе при использовании параметра PyArrow.
ds.write_dataset(
data,
output_path,
format = "parquet",
min_rows_per_group=1000000,
max_rows_per_group=1000000,
partitioning=ds.partitioning(pa.schema([("type", pa.string())])),
existing_data_behavior = "overwrite_or_ignore"
)
Метод Polars занимает больше времени, а опция row_group_size не работает при использовании параметров PyArrow:
output.write_parquet(
file=output_path,
use_pyarrow=True,
pyarrow_options = {"partition_cols": partition_cols},
row_group_size=1000000,
)
Это работает, если вы передадите его через pyarrow_options dict
Я предполагаю, что там масса новых файлов, верно?