2010YOUY01 opened a new pull request, #15017: URL: https://github.com/apache/datafusion/pull/15017
## Which issue does this PR close? <!-- We generally require a GitHub issue to be filed for all bug fixes and enhancements and this helps us generate change logs for our releases. You can link an issue to this PR using the GitHub syntax. For example `Closes #123` indicates that this PR will close issue #123. --> - Closes #. NA ## Rationale for this change <!-- Why are you proposing this change? If this is already explained clearly in the issue then this section is not needed. Explaining clearly why changes are proposed helps reviewers understand your changes and offer better suggestions for fixes. --> I came across one sorting query with memory limit fail indefinitely, here is a simpler reproducer (running in `datafusion-cli` with commit 75977692c) ```sh # Compile datafusion-cli cargo run --profile release-nonlto -- --mem-pool-type fair -m 10M ``` 2 sort queries are executed: Q1 get executed with no issue, Q2 has smaller input size than Q1, but it failed. ``` DataFusion CLI v46.0.0 > set datafusion.execution.sort_spill_reservation_bytes = 3000000; 0 row(s) fetched. Elapsed 0.001 seconds. > select * from generate_series(1,10000000) as t1(v1) order by v1; ...Query succeed > select * from generate_series(1,9000000) as t1(v1) order by v1; Resources exhausted: Failed to allocate additional 65536 bytes for ExternalSorterMerge[0] with 0 bytes already allocated for this reservation - 49152 bytes remain available for the total pool ``` ### Query failure reason At the final stage of sorting, all buffered in-memory batches and all the spilled files will be sort-preserving merged at the same time, and this caused the issue. https://github.com/apache/datafusion/blob/75977692c12bda72301ccf65067532c5135fbd5c/datafusion/physical-plan/src/sorts/sort.rs#L342-L355 For example, there is one workload, let's say it's executing in a single partition. It's memory limit can hold 10 batches. - Sorting 100 batches can be executed without issue: - Every time 10 batches are read, mempool is full and one spill file will be written to disk - Finally, there are 10 spill files, only one batch of each file is required to load to memory at the same time, so there is enough memory budget to do the final merging. - Sorting 49 batches fails: - When the input is exhausted, there are 9 in-mem batches and 4 spill files. 9 + 4 batches are required to load to memory for final merging, it exceeds the memory pool limit which is around 10 batches. A common workaround I believe is to set `datafusion.execution.sort_spill_reservation_bytes` to larger, its used for extra space for merging. However, workloads' row/batch size can vary drastically, also it's possible to see the case in-memory batches has almost reached the memory limit but not yet triggered on spilling, so this parameter is very tricky to configure it correct. To make this simpler, we can always spill the in-memory batches (if it has spilled previously) at the final stage. ## What changes are included in this PR? Change the final sort-preserving merge logic of sorting: when it has spilled before, always spill all in-mem batches first, then start the merging phase. <!-- There is no need to duplicate the description in the issue here but it is sometimes worth providing a summary of the individual changes in this PR. --> ## Are these changes tested? <!-- We typically require tests for all PRs in order to: 1. Prevent the code from being accidentally broken by subsequent changes 2. Serve as another way to document the expected behavior of the code If tests are not included in your PR, please explain why (for example, are they covered by existing tests)? --> Regression test is added ## Are there any user-facing changes? <!-- If there are user-facing changes then we may require documentation to be updated before approving the PR. --> No <!-- If there are any breaking changes to public APIs, please add the `api change` label. --> -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: github-unsubscr...@datafusion.apache.org For additional commands, e-mail: github-h...@datafusion.apache.org