Skip to content

Epic: Cost-Based Dictionary Encoding #24111

Description

@Rich-T-kid

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

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 in the aggregation pipeline this would be much more efficient. example

Related issues

Additional context

#23187 (comment)
#23187 (comment)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions