Skip to content

Stop ParquetSink from retaining every written file's ParquetMetaData - #88

Closed
xudong963 wants to merge 1 commit into
branch-55from
xudong963/parquet-sink-drop-written-metadata
Closed

xudong963 wants to merge 1 commit into
branch-55from
xudong963/parquet-sink-drop-written-metadata

Conversation

@xudong963

@xudong963 xudong963 commented Nov 3, 2026 •

Copy link
Copy Markdown

Which issue does this PR close?

Rationale for this change

ParquetSink kept every written file's ParquetMetaData in written: HashMap<Path, ParquetMetaData> for the lifetime of the sink, i.e. for the whole partition write. Nothing in the engine reads that map; only the ParquetSink unit tests in datafusion-core did, through ParquetSink::written().

The retention also did not stop at the map: the writer tasks returned (Path, ParquetMetaData) through a JoinSet that is only drained after the demux loop has announced the last file, so completed tasks' metadata sat in the JoinSet for just as long.

What changes are included in this PR?

  • Writer tasks now reduce the closed file's metadata to (rows, compressed bytes) (written_file_counts) and drop the ParquetMetaData inside the task. The sink keeps no per-file state after a file is closed; the rows_written / bytes_written metrics are unchanged.
  • The written map, ParquetSink::written() and the duplicate-path check that rode on the map are removed. Output paths are generated by the demuxer (<write_id>_<n>), so the check never had a way to fire.
  • parking_lot is dropped from datafusion-datasource-parquet; the mutex was its only use.
  • The datafusion-core ParquetSink tests get a SinkTestStore fixture (temp dir + LocalFileSystem) and read each written file's footer back from the store instead of asking the sink. As a side effect the temp directory now lives for the whole test instead of being deleted right after creation and silently recreated by the object store on the first write.

Are these changes tested?

  • cargo test -p datafusion --lib -- datasource::file_format::parquet::tests::parquet_sink (8 tests: single/partitioned/parallel writes, arrow-schema metadata, extensions, memory reservation) passes.
  • cargo clippy -p datafusion-datasource-parquet --all-targets -- -D warnings, cargo fmt --all and taplo format --check are clean.

Are there any user-facing changes?

ParquetSink::written() is removed. Atlas does not call it; per-file metadata after a write is the subject of apache#23472 and would need a different, opt-in design.

ParquetSink kept each written file's ParquetMetaData in a HashMap for the
lifetime of the sink, and its writer tasks also handed the metadata back
through a JoinSet that is only drained once the last file has been
announced. Nothing in the engine read either; only the datafusion-core
unit tests used ParquetSink::written().

For Atlas this meant a 5-day options NBBO weekly rollup (~700 output
files) grew ~1 GiB of RSS per 10 GB written outside the memory pool
until the 64 GiB container limit killed it.

Writer tasks now reduce the closed file's metadata to its row count and
compressed byte count for the rows_written / bytes_written metrics and
drop the ParquetMetaData inside the task. The written map,
ParquetSink::written() and the parking_lot dependency go away. The core
tests read the footers back from a temporary local object store instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant