ClickHouse / ClickHouse/ClickHouse

Automatic parallel replicas: some plan shapes do not hash-match with parallel_replicas_plan_based, so no statistics are collected

Open
#118,265 2 comments 0 reactions 0 assignees View on GitHub
comp-parallel-replicas
Dominant language
C++
Stars
49.9k
Forks
9k
Avg merge
21h 32m
Merged PRs (30d)
515

Description

https://github.com/ClickHouse/ClickHouse/pull/115788 taught automatic parallel replicas to recognize the plan-based reading step, which is what lets it collect statistics at all when `parallel_replicas_plan_based` is on. Some shapes still do not match, so no statistics are collected and the optimization never enables parallel replicas for them.

The matching itself is in `findCorrespondingNodeInSingleNodePlan` (`src/Processors/QueryPlan/Optimizations/considerEnablingParallelReplicas.cpp`): the node that would sit at the top of the replicas' plan is looked up in the single-node plan by the bottom-up hash from `calculateHashTableCacheKeys`. When the two plan builds differ by even one pass-through step the hashes differ and the lookup logs `Cannot find step with matching hash in single-node plan`.

Known cases, each of which had to pin `parallel_replicas_plan_based = 0`:

- **`04341_autopr_mode1_apply_join`** - with join runtime filters on, the plan-based local branch carries an extra identity `Expression` between the `Aggregating` and the `Join`, so the hashes diverge. `INNER` and `RIGHT` report `ParallelReplicasUsedCount = 0`; `LEFT` (no runtime filter) still applies. With `enable_join_runtime_filters = 0` it matches and applies.
- **`03634_autopr_input_bytes_estimation_compact`** and **`04838_autopr_input_bytes_estimation_compact_codec`** - plain reads, where the fragment is the reading step itself, so `considerEnablingParallelReplicas` bails with "The matched node is the reading step itself, cannot estimate the amount of data sent to the initiator". The query-based implementation lands on the `Expression` above the read instead, because `findTopNodeOfReplicasPlan` descends one level past a top `Expression`/`Filter` for every `Union` child - a descent meant for the remote branch.

A related detail worth deciding on: a step whose own hash contribution is 0 (a rename-only `Expression`) is documented as "transparent", but `calculateHashTableCacheKeys` still re-hashes its child through it, so an extra transparent step shifts every ancestor hash. Making it truly transparent would fix the join case, but it also makes such a step hash-identical to its child, so the "first node with a matching hash" scan over an `unordered_map` in `findCorrespondingNodeInSingleNodePlan` would need to become deterministic at the same time.

Going the other way, plan-based already matches a shape the query-based implementation does not: `03707_autopr_unsupported_cases` lists `unsupported_aggregation_over_aggregation` as unmatchable, and under plan-based it matches and collects. That case is pinned to the query-based implementation so the test keeps documenting the query-based limits.

Related: https://github.com/ClickHouse/ClickHouse/pull/115788
Related: https://github.com/ClickHouse/ClickHouse/pull/112351

Contributor guide

Open the contributing guide

Research direction

Start in src/Processors/QueryPlan/Optimizations/considerEnablingParallelReplicas.cpp, especially findCorrespondingNodeInSingleNodePlan and the hash keys from calculateHashTableCacheKeys. Run the named 04341_autopr_mode1_apply_join, 03634_autopr_input_bytes_estimation_compact, and 04838_autopr_input_bytes_estimation_compact_codec tests to reproduce the unmatched shapes. Compare the plan-based and query-based behavior, then make the matching deterministic and verify that statistics are collected without the pinned settings.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
databases, distributed-systems, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.