apache / apache/datafusion

Epic: Cost-Based Dictionary Encoding

Open
#24,111 13 comments 3 reactions 0 assignees View on GitHub
enhancement
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?

Aggregating over low-cardinality string columns (e.g. GROUP BY on category/status-like fields) is slower than it needs to be, because DataFusion has no way to represent these as dictionary-encoded arrays automatically. Today, getting the performance benefit requires manually casting columns yourself, there's no config to opt in, no way to bound it by cardinality, and no mechanism for the engine to decide this on its own based on the data or query shape.
### Describe the solution you'd like

- [ ] #24112
- [ ] #24113
- [x] #22891
- [ ] #24114
- [ ] #24116
- [ ] #24117

Together these give users manual control first (enable dictionary reads, set a cardinality threshold), then build the statistics and optimizer support needed for DataFusion to make that same decision automatically. The end goal is a physical plan optimization that casts low-cardinality string columns to dictionary arrays before aggregation when the stats justify it, without requiring any manual intervention.

**Currently**
```
SELECT
gender,
shirt_size,
marital_status,
region,
count(*) AS cnt,
sum(amount) AS total_amount,
avg(amount) AS avg_amount,
min(amount) AS min_amount,
max(amount) AS max_amount
FROM orders
GROUP BY gender, shirt_size, marital_status, region
ORDER BY gender, shirt_size, marital_status, region;
```

With 20 million rows, we'd repeatedly process the same string data over and over, even though Parquet metadata could tell us up front that these columns are low cardinality (gender: 2, shirt_size: 4, marital_status: 2, region: 10)

once this epic is complete we'd have something like
```
SET datafusion.parquet.dict_read_enable = true
SET datafusion.parquet.dict_threshold = .05

SELECT
gender,
shirt_size,
marital_status,
region,
count(*) AS cnt,
sum(amount) AS total_amount,
avg(amount) AS avg_amount,
min(amount) AS min_amount,
max(amount) AS max_amount
FROM orders
GROUP BY gender, shirt_size, marital_status, region
ORDER BY gender, shirt_size, marital_status, region;
```
with [dictionary arrays being supported directly ](https://github.com/apache/datafusion/pull/23187) in the aggregation pipeline this would be much more efficient. [example](https://github.com/apache/datafusion/pull/23187#issuecomment-5193826956)

Related issues

- [X] https://github.com/apache/datafusion/issues/23993
- [ ] https://github.com/apache/datafusion/issues/24089
- [ ] https://github.com/apache/datafusion/pull/25185
- [ ] https://github.com/apache/datafusion/issues/23127
- [x] #23921
- [x] https://github.com/apache/arrow-rs/issues/10590
- [x] https://github.com/apache/arrow-rs/pull/10765
- [x] https://github.com/apache/arrow-rs/issues/10830
- [x] https://github.com/apache/arrow-rs/issues/10650

### Additional context

https://github.com/apache/datafusion/pull/23187#issuecomment-5190571128
https://github.com/apache/datafusion/pull/23187#issuecomment-5192617111

Contributor guide

Open the contributing guide

Research direction

Start by reading the linked child issues (#24112, #24113, #22891, #24114, #24116, and #24117) and the referenced dictionary-array aggregation pull request #23187. Done means completing the checklist so DataFusion can use statistics and query shape to choose dictionary encoding automatically before aggregation.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sql
Domain
databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.