[fix](join) Eliminate joins with never-true conditions - #66806
Draft
mrhhsg wants to merge 1 commit into
Draft
Conversation
### What problem does this PR solve?
Issue Number: None
Related PR: None
Problem Summary: A LEFT or RIGHT OUTER JOIN whose condition folds to FALSE or NULL remained in the logical plan, so its null-padded outputs were not represented as uniform NULL values. A later null-rejecting INNER JOIN could therefore miss folding to an empty relation and execute large nested-loop intermediates even though the result was known to be empty. Replace never-matching one-sided outer joins with a projection over the preserved child and typed NULL aliases, replace never-matching inner and cross joins with an empty relation, and reuse the elimination after join constant propagation.
### Release note
Improve query performance by eliminating joins whose conditions are constant FALSE or NULL.
### Check List (For Author)
- Test:
- Unit Test: `./run-fe-ut.sh --run org.apache.doris.nereids.rules.rewrite.EliminateJoinConditionTest`
- Behavior changed: Yes (semantically redundant joins are removed; query results are unchanged)
- Does this need documentation: No
Contributor
|
Thank you for your contribution to Apache Doris. Please clearly describe your PR:
|
Member
Author
|
/review |
Contributor
There was a problem hiding this comment.
Opinion: approve. I found no blocking or actionable inline issue in the reviewed diff.
Critical checkpoint conclusions
- Goal and correctness: The change accomplishes the stated goal. A never-true inner/cross join becomes an empty relation; a one-sided outer join becomes the preserved child plus typed NULL aliases; and constant propagation can reapply that elimination so a lower null-padded result can simplify an upper join. The replacement preserves row multiplicity, output order, ExprIds, names, qualifiers, data types, and nullable output semantics.
- Scope and clarity: The change is focused on one rewrite helper, its use from constant propagation, and targeted FE unit tests. It reuses the existing join-condition rule instead of duplicating the transformation.
- Concurrency: This is a statement-local logical-plan rewrite. It adds no shared mutable state, threads, locks, or concurrent lifecycle.
- Lifecycle/static initialization: No new global/static state, ownership protocol, or non-obvious lifecycle is introduced.
- Configuration: No configuration item is added or changed.
- Compatibility: No public API, function symbol, serialized format, persisted metadata, RPC, or FE-BE protocol changes are involved, so rolling-upgrade compatibility is unaffected.
- Parallel paths: The join-type matrix was checked. Mark, full outer, null-aware anti, ordinary semi/anti, and ASOF joins retain their distinct behavior as intended. In the production pipeline, later filter pushdown and empty-relation cleanup remove decisive semi-join work and prevent the alleged cross-product cost for ordinary anti joins.
- Conditional handling: Removing literal TRUE conjuncts remains safe. Literal FALSE/NULL elimination is fenced to non-mark joins and only the join types whose SQL three-valued semantics make the result exact; the excluded join types need different semantics.
- Test coverage: The FE tests cover existing TRUE removal, FALSE inner elimination, NULL/FALSE left and right outer elimination, output reconstruction, and nested null propagation into an upper inner join. This is appropriate focused coverage for the localized planner rewrite; no end-to-end regression case is added.
- Test results: The review runner did not run builds or tests, as required by its review-only instructions. The PR reports the five focused unit tests passing. Current CI shows CheckStyle and the other completed checks passing; the automated code-review check is this pending run.
- Observability: No new user-visible failure mode or distributed runtime path is introduced; additional logs or metrics are not warranted for this deterministic planner rewrite.
- Persistence and transactions: No EditLog, replay, transaction, failover, or persistent-state path is touched.
- Data writes and FE-BE propagation: The change does not write data and adds no variable or plan protocol field that must be propagated to BE.
- Performance: The rewrite removes unnecessary join execution. Projection construction is linear in output width, and the complete downstream rewrite pipeline revealed no material regression or missed hot-path work.
- Other concerns: Error handling, memory safety, volatile-expression evaluation, logical-property invalidation, rewrite ordering, and termination were checked; no additional issue was found.
User focus
No additional user-provided focus points were supplied. The full three-file change and its relevant upstream/downstream planner paths were reviewed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What problem does this PR solve?
Issue Number: None
Related PR: None
Problem Summary:
A one-sided outer join whose condition folds to
FALSEorNULLstill remained in the logical plan. Although the nullable side can only produce NULL-padded columns, the optimizer did not expose those columns as uniform NULL values. Consequently, a later null-rejecting inner-join predicate could fail to fold to an empty relation and execute very large nested-loop intermediates for a query whose result is already known to be empty.This change:
Mark joins, semi/anti joins, full outer joins, and ASOF joins retain their existing behavior.
Release note
Improve query performance by eliminating joins whose conditions are constant
FALSEorNULL.Check List (For Author)
./run-fe-ut.sh --run org.apache.doris.nereids.rules.rewrite.EliminateJoinConditionTest(5 tests passed)