Sort ClickBench data using 4GB on standard laptop (spilling)
- Dominant language
- Rust
- Stars
- 9.3k
- Forks
- 2.4k
- Avg merge
- 3d 7h
- Merged PRs (30d)
- 344
Description
### Is your feature request related to a problem or challenge?
While working with @zhuqi-lucas on https://github.com/apache/datafusion/pull/19042 we noticed it is not possible to sort the hits.parquet dataset
Get the data
```shell
./benchmarks/bench.sh data clickbench_1
```
Try to resort it using 4G of memory (on a 20 core Mac M3 laptop):
```shell
datafusion-cli -m 4G -c "COPY (SELECT * FROM 'benchmarks/data/hits.parquet' ORDER BY \"EventTime\") TO 'hits_sorted.parquet' STORED AS PARQUET;"
```
Results in
```
DataFusion CLI v51.0.0
Error: Not enough memory to continue external sort. Consider increasing the memory limit, or decreasing sort_spill_reservation_bytes
caused by
Resources exhausted: Additional allocation failed for ExternalSorter[7] with top memory consumers (across reservations) as:
ExternalSorterMerge[4]#11(can spill: false) consumed 883.8 MB, peak 883.8 MB,
ExternalSorterMerge[1]#5(can spill: false) consumed 812.6 MB, peak 812.6 MB,
ExternalSorterMerge[9]#21(can spill: false) consumed 764.8 MB, peak 764.8 MB.
Error: Failed to allocate additional 13.7 MB for ExternalSorter[7] with 0.0 B already allocated for this reservation - 1088.1 KB remain available for the total pool
```
As @2010YOUY01 has documented in https://datafusion.apache.org/user-guide/configs.html#memory-limited-queries, this query does run to completion with fewer target partitions for example 1:
```sql
SET datafusion.execution.target_partitions = 1;
```
Then this succeeds
```shell
datafusion-cli -m 4G -c "SET datafusion.execution.target_partitions = 1; COPY (SELECT * FROM 'benchmarks/data/hits.parquet' ORDER BY \"EventTime\") TO 'hits_sorted.parquet' STORED AS PARQUET;"
```
However, 2 target partitions still fails:
```shell
andrewlamb@Andrews-MacBook-Pro-3:~/Software/datafusion2$ datafusion-cli -m 4G -c "SET datafusion.execution.target_partitions = 2; COPY (SELECT * FROM 'benchmarks/data/hits.parquet' ORDER BY \"EventTime\") TO 'hits_sorted.parquet' STORED AS PARQUET;"
DataFusion CLI v51.0.0
0 row(s) fetched.
Elapsed 0.000 seconds.
Error: Not enough memory to continue external sort. Consider increasing the memory limit, or decreasing sort_spill_reservation_bytes
caused by
Resources exhausted: Additional allocation failed for ExternalSorter[0] with top memory consumers (across reservations) as:
ExternalSorter[1]#5(can spill: true) consumed 3.2 GB, peak 3.5 GB,
ExternalSorterMerge[1]#6(can spill: false) consumed 767.1 MB, peak 1773.9 MB,
ExternalSorterMerge[0]#4(can spill: false) consumed 10.0 MB, peak 1679.3 MB.
Error: Failed to allocate additional 27.6 MB for ExternalSorter[0] with 0.0 B already allocated for this reservation - 20.7 MB remain available for the total pool
```
### Describe the solution you'd like
I would like DataFusion to be able to complete such queries with a reasonable amount of RAM without having to tune the target partitions
### Describe alternatives you've considered
Maybe there could be be some "rule of thumb" for the required resources -- for example, perhaps we could make sure queries run with 1 GB of RAM per core (and adjust the batch size / target partitioning automatically if needed)
### Additional context
_No response_
Contributor guide
Research direction
Start by reproducing the failure with benchmarks/bench.sh data clickbench_1 and the datafusion-cli COPY command against benchmarks/data/hits.parquet using 4G and the default target partitions. Read the external sort and spilling behavior indicated by the error, then compare it with target_partitions set to 1 or 2. Done means the sort completes with reasonable RAM without manually tuning target partitions.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100