apache / apache/iceberg-python

fix(streaming-write): use rolling ParquetWriter + OutputStream.tell() for spec-correct file sizes and bounded memory

未關閉
#3,388 0 則留言 1 個 reaction 已指派 0 人 在 GitHub 檢視
主要語言
Python
星號
1.1k
分支
581
平均合併
1 天 13 小時
30 天內合併 PR
76

描述

## Background

PR #3335 added `pa.RecordBatchReader` as a valid input to `Table.append`/`Table.overwrite` using a buffered bin-pack approach (`bin_pack_record_batches`). That implementation has two acknowledged caveats called out in its docstrings:

1. **Memory bound**: peak memory is `N_workers × write.target-file-size-bytes` (~4 GiB at defaults) — better than materialising everything, but not constant.
2. **Byte semantics**: `write.target-file-size-bytes` is interpreted as uncompressed in-memory Arrow bytes, not on-disk compressed Parquet bytes. Resulting files are typically 3–10× smaller than the property suggests — diverging from the Java/Spark/Flink writers.

## Proposed fix

Replace the bin-pack approach with a rolling `pq.ParquetWriter` driven by `OutputStream.tell()` (added in #2998 specifically for this purpose):

```python
with output_file.create(overwrite=True) as fos:
with pq.ParquetWriter(fos, schema=..., ...) as writer:
writer.write_batch(first_batch)
while fos.tell() < target_file_size: # ← compressed on-disk bytes
batch = next(batches)
writer.write_batch(batch)
```

This delivers:

- **Spec-correct file sizes**: `tell()` reports compressed on-disk bytes, so `write.target-file-size-bytes` finally means what the Iceberg spec intends — consistent with the Java/Spark/Flink writers.
- **Truly bounded memory**: peak RSS is bounded by one input batch + Parquet page buffer (~1 MiB × columns) + S3 multipart pool (~5 MiB × ~8 parts), regardless of `target_file_size`, dataset size, or number of files produced.
- **No public API change**: same `tbl.append(reader)` / `tbl.overwrite(reader)` interface.

## Fix

#3336

貢獻指南

這個儲存庫沒有索引到貢獻指南

研究方向

從 RecordBatchReader 輸入的 Table.append/Table.overwrite 開始,追蹤 bin_pack_record_batches 路徑,然後閱讀提議的 pq.ParquetWriter 與 OutputStream.tell() 用法。完成的標準是 target_file_size_bytes 反映壓縮後的磁碟大小,並且在不變更 public API 的情況下讓記憶體維持有界;issue 未指定測試檔案。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
python
領域
data
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
冷清
描述清晰度
基本清楚
新手友好度
45/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。