You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
cost: route inner-unique INNER NL through SEMI early-stop branch
PG's final_cost_nestloop (costsize.c:3389) shares the SEMI/ANTI
early-stop code with INNER joins that have inner_unique=true: each
outer row matches at most one inner row, so the unmatched-outer arm
bills only "1-tuple worth of rescan" against an indexed inner instead
of a full inner_rescan_run_cost. CCostModelPG::CostNLJoin was only
entering the early-stop branch for explicit SEMI/ANTI ops, so a plain
INNER NL on a PK / unique-index lookup paid the full rescan per outer
row -- pushing the optimizer toward HashJoin on PK-lookup plans.
Detect inner-unique cheaply at cost time: walk the join predicate's
conjuncts, keep only inner_ident=outer_ident equalities, collect the
inner-side colrefs into a set, and test it against the inner's
CKeyCollection via FKey(...,fExactMatch=false) -- the same primitive
CXformLeftSemiJoin2InnerJoin uses to decide whether to interpose a
GbAgg for dedup.
Only fire for uncorrelated InnerNLJoin / InnerIndexNLJoin (correlated
IndexApply already bills exactly one probe per outer row, no
double-correction wanted). Inside the early-stop branch the only new
fork is match_count = 1.0 for the inner-unique case; outer_match_frac
falls through to the existing semi-style output/outer formula, which
is exactly the inner-unique semantics (each matched outer => 1 row).
Verification:
- cost_align same-plan counts unchanged (311 / 183 in-tol / 7 baseline
FAIL / 121 diff-plan) and row-level cost diff against baseline empty
- TPC-H SF=1 cost_model=pg: all 22 ratios stable vs prior baseline
(Q17 21.7x, Q20 5.25x, Q9 1.48x)
0 commit comments