Skip to content

Represent Hive/value partitioning without claiming Partitioning::Hash #23436

Description

@Phoenix500526

Is your feature request related to a problem or challenge?

Follow-up from #23189

File scans for Hive/value-partitioned data currently represent their output partitioning as Partitioning::Hash on the partition columns. This lets the optimizer avoid repartitioning for key-partitioned operators, but the data was
not actually assigned to partitions by DataFusion's hash partitioner.

This makes Partitioning::Hash carry multiple meanings:

  • DataFusion hash partitioning with a particular hash implementation / seed
  • another hash implementation / seed
  • Hive/value-based file grouping by partition column values
  • potentially other source-defined key partitioning methods

These partitioning methods can all provide key colocation, but they are not necessarily co-partitioned by partition index. Treating them all as Partitioning::Hash can make later optimizer decisions and dynamic filtering
decisions brittle or incorrect if they rely on partition compatibility.

Describe the solution you'd like

Discuss and design a more precise representation for value-based physical partitioning. Possible directions from the PR discussion include:

  • add a new Partitioning::Value / ValuePartitioned variant
  • represent Hive/value partitioning as Partitioning::Range when values and ordering are available
  • make the partitioning method explicit, e.g. hash algorithm/seed vs column value grouping
  • explore whether Partitioning should become extensible for source-defined partitioning methods

The design should distinguish:

  • satisfying a Distribution::KeyPartitioned requirement, where key colocation may be enough
  • proving co-partitioning / partition-index compatibility between two inputs, where the exact partitioning method and value-to-partition mapping matter

Describe alternatives you've considered

No response

Additional context

Related issues and PRs:

Relevant review thread:

CC @gene-bordegaray @alamb @gabotechs @jayshrivastava

Activity

  1. gstamatakis95 commented on Sep 10, 2026

    @gstamatakis95

    take

  2. jayshrivastava commented on Oct 15, 2026

    @jayshrivastava
    Contributor

    @gstamatakis95 Are you still working on this?

  3. jayshrivastava commented on Oct 15, 2026

    @jayshrivastava
    Contributor

    Ah I just saw #25279.

    That PR implements support for hive partitioning, detecting that files are Hive partitioned and automatically giving the data source a Range partitioning property. That's a reasonable change but I think we should keep this issue open since it's tracking a more generalized problem.

    Notably Trino supports the following:

    • Can we support a non-range style of partitioning? For example, my data might be partitioned without any presumed sort order like p1 = {A, C, E}, p2 = {B, D}, so Range doesn't apply
    • Not assuming a file-backed data source. The data source might be a wrapper on top of an external service that exposes partitions (notably datafusion's hash function cannot be pushed down to another service / language).
    • Dynamic filtering works without specifying the partitioning expression / hash function*

    *caveat - Filters are unioned across partitions within a machine. However, there's still a distinct filter per machine.

    I think it would be good to support the above for feature parity with Trino.

  4. jayshrivastava commented on Oct 16, 2026

    @jayshrivastava
    Contributor

    What if we added a custom partitioning scheme which stores an identifier which helps check equality?

    #[derive(Debug, Clone)]
    pub enum Partitioning {
        RoundRobinBatch(usize),
        Hash(Vec<Arc<dyn PhysicalExpr>>, usize),
        Range(RangePartitioning),
        /// NEW: denote that we are partitioned on these columns using an identifier to combine the partitioning scheme.
        Custom(Vec<Arc<dyn PhysicalExpr>>, num_partitions: usize, identifier: usize),
        UnknownPartitioning(usize),
    }

    The only edge case I think can think of is that CASE expressions in dynamic filters won't work because the partitions are only defined by an identifier.

  5. jayshrivastava commented on Oct 16, 2026

    @jayshrivastava
    Contributor

    @kosiew @Phoenix500526 @gabotechs @alamb, what do y'all think about the above two comments?

    I have some use cases that would benefit from custom partitioning (ie. it doesn't fit into Hash nor Range partitioning) to avoid repartitions during co-partitioned joins and aggregations.

  6. alamb commented on Oct 16, 2026

    @alamb
    Contributor

    What if we added a custom partitioning scheme which stores an identifier which helps check equality?

    Are you suggesting that we add a custom partitioning as part of this PR? Or as a follow on project?

    In my mind, maybe it is time to move to a trait based partitioning scheme rahter than an enum (which would naturally allow any arbitrary partitioning scheme to be supported) 🤔

  7. jayshrivastava commented on Oct 19, 2026

    @jayshrivastava
    Contributor

    Are you suggesting that we add a custom partitioning as part of this PR? Or as a follow on project?

    Probably a follow up.

    In my mind, maybe it is time to move to a trait based partitioning scheme rahter than an enum (which would naturally allow any arbitrary partitioning scheme to be supported) 🤔

    Ack! I think I agree at a high level. I'll keep an eye out for use cases and see if I can find time to look into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to 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