Repository navigation
Let ParquetSink opt out of retaining written files' ParquetMetaData, and do so for COPY / INSERT - #27027
Let ParquetSink opt out of retaining written files' ParquetMetaData, and do so for COPY / INSERT#27027xudong963 wants to merge 1 commit into
Conversation
|
I am wondering if users of datafusion may have used that returned parquet metadata for creating external row group indexes so while internally its not used it could potentially be disruptive to users. Maybe it would be safer to keep existing functionality as is and add the ability to opt out of returning metadata? |
Good call, thanks @matthewmturner! I let llm re-check all github repos, lol, and there are real users of I’ll switch this PR to keep |
ParquetSink kept each written file's ParquetMetaData until the sink was dropped: the writer tasks returned it through a JoinSet that is only drained once the last file has been announced, and the join loop then stored it in the `written` map. The metadata carries every column chunk's statistics and page indexes, so a COPY or INSERT that writes many files grew memory outside the pool until it finished, although nothing on that path reads the map. ParquetSink::written() does have users that construct the sink themselves (InfluxDB, datafusion_iceberg, LakeSoul), so the map stays and keeps its default. Add ParquetSink::with_retain_written_metadata(bool) and turn it off for the sinks ParquetFormat creates. Writer tasks now return only their file's row and byte counts; record_written_file stores or drops the metadata inside the task, so nothing is buffered in the JoinSet either. Closes apache#27026
247c0bb to
88929ae
Compare
Which issue does this PR close?
ParquetSink).Rationale for this change
A
COPY ... TO ... STORED AS PARQUETorINSERT INTOthat writes many files keeps growing in memory until the statement finishes, outside the memory pool.ParquetSinkkept every written file'sParquetMetaData(all column chunk statistics plus page indexes) until the sink was dropped, in two places: the writer tasks returned(Path, ParquetMetaData)through aJoinSetthat is only drained after the demux loop has announced the last file, and the join loop then moved each one intowritten: HashMap<Path, ParquetMetaData>.Nothing on the
COPY/INSERTpath reads that map.ParquetSink::written()does have users who construct the sink themselves and read the metadata of the one or few files it wrote: InfluxDB 3 (parquet_file/src/serialize.rs),datafusion_iceberg(buildsDataFiles from it) and LakeSoul (file_sink_writer.rs). Their behavior is unchanged. #27026 has the production numbers: a ~700-file partition write grew RSS by roughly 1 GiB per 10 GB written until it was OOM-killed.What changes are included in this PR?
ParquetSink::with_retain_written_metadata(bool), defaulttrue. Withfalse,written()returns an empty map and no file metadata is kept.ParquetFormat::create_writer_physical_planturns it off for the sinks it builds forCOPYandINSERT, since nothing on that path reads the metadata.record_written_fileruns inside the task: it stores theParquetMetaDatain the map when retention is on, or drops it right there when it is off. Either way nothing is buffered in theJoinSetuntil the last file is announced. The duplicate path check moves with it. Metrics are unchanged.parquet_sink_write_without_retained_metadata), and an upgrade guide entry for theParquetFormatbehavior change.The retention switch is not part of the plan's protobuf encoding, like the map itself; a sink that went through a round-trip is created with
ParquetSink::newand retains metadata. A proto field could be added if we wantCOPYon remote executors to benefit too.What is the testing strategy for this PR?
parquet_sink_write_without_retained_metadatachecks that a sink with retention off still writes and counts the rows and thatwritten()is empty.parquet_sink_*tests (default retention) coverwritten()for single, partitioned and parallel writes and are unchanged.cargo test -p datafusion --lib -- datasource::file_format::parquet::tests::parquet_sinkpasses (9 tests).cargo clippy --all-targets --all-features -D warningsondatafusion-datasource-parquet,cargo clippy --testsondatafusionandcargo check --testsondatafusion-protoare clean.Are there any user-facing changes?
New builder method
ParquetSink::with_retain_written_metadata. Sinks created byParquetFormatno longer retain written file metadata; anyone downcasting the sink of such a plan to callwritten()afterwards would now get an empty map and should construct theParquetSinkthemselves (documented in the upgrade guide). No existing API is removed.