Join-order enumeration
Count a bounded search space, use subproblem reuse, and retain physical properties when exploring legal join trees.
On this page
The question for today
What you’ll understand
- Distinguish leaf permutations, binary tree shapes, and semantically legal plans.
- Calculate small search-space counts under explicit enumeration conventions.
- Explain why pruning and heuristic search trade planning effort against plan quality.
Joining the same tables in different orders can create very different intermediate results. Finding a good order is itself computational work, and a production planner cannot explore every imaginable physical plan indefinitely. This lesson separates a clean combinatorial model from the legal, property-aware search a real optimizer performs, so that neither a factorial count nor a heuristic setting is mistaken for a guaranteed winning strategy.
Count only after defining what differs
For n distinct labeled inputs and one fixed left-associated binary tree shape, there are n factorial leaf permutations before considering equivalence or restrictions. Allowing every ordered full binary tree shape adds a Catalan-number factor. These counts deliberately distinguish left and right children and allow arrangements that a real planner may reject, including unnecessary Cartesian products. Commutative equivalent expressions and unsupported join forms can reduce the useful search. State the counting convention instead of quoting one dramatic number as the exact number of physical plans in a particular database.
A join graph records which inputs have connecting predicates. Searching connected subproblems can avoid many Cartesian combinations. Outer joins, lateral dependencies, semijoins, and other semantic constraints can restrict legal reorderings further. The optimizer must preserve those dependencies even if another order looks smaller under a naïve cardinality formula. A three-table inner-join identity is not a license to rotate an arbitrary mixed outer-join tree. Correctness determines the feasible candidates before estimated intermediate size determines which are attractive.
Reuse subproblems without discarding useful properties
Dynamic programming can build plans for smaller input subsets and reuse them while constructing larger subsets. There are exponentially many possible subsets even before partitioning each subset into children. A simple scalar recurrence chooses the cheapest combination under an assumed additive cost model. That illustrates optimal substructure, but a production optimizer needs richer state. The cheapest unordered result for a subset may lose to a slightly more expensive ordered result once a parent can avoid sorting. Parameterization and parallel properties create further distinctions.
Pruning is justified only relative to the retained state and cost assumptions. If two subplans provide the same required properties and one has no advantage under the model, the dominated one may be unnecessary. Discarding every higher scalar cost regardless of properties is different. Cardinality errors then affect both the cost of a candidate and which alternatives survive exploration. Improving statistics can consequently help more than increasing search effort, while an excellent search still cannot recover a genuinely unavailable access path or an illegal transformation.
Budget planning effort as well as execution
PostgreSQL uses configurable join collapsing and can switch to genetic search beyond a configured relation-count threshold. Heuristic search reduces explored candidates and need not find the globally best modeled plan. Constraining explicit join order can reduce planning time or direct a known useful shape, but it can also prevent a better alternative. Evaluate representative parameters and include planning time in an end-to-end objective. A millisecond saved in execution does not justify seconds of repeated planning for a high-frequency short query without examining reuse and amortization.
The cache lab offers a limited memo-reuse analogy. Reset, set both C=4 and s=4, predict twelve hits among the initial sixteen requests, then Play or Step. Separately Reset, set both C=3 and s=4, predict zero initial hits, then Play or Step. The address stream repeats four fixed identities and the cache is ordinary toy LRU. It is not a join enumerator or an optimizer memo and contains no physical properties. Use it only to explain why losing reusable subproblem state can recreate work, then describe which richer keys a real planner would need.
Work it through
Four relations under three explicit counting conventions
Four distinct input relations are freely arranged in a teaching model. Ignore join-graph restrictions and semantic pruning, distinguish left/right children, and count one left-associated shape, all ordered full binary shapes, and nonempty subsets.
One fixed left-associated shape has 4!=4×3×2×1=24 leaf permutations. This includes permutations later identified as equivalent under join commutativity.
There are C3=(1/4)×binomial(6,3)=5 ordered full binary tree shapes. Multiplying by the 24 label permutations gives 120 syntactic ordered bushy trees.
The subset dynamic-programming state universe contains 2^4−1=15 nonempty subsets, including four singleton inputs. Each larger subset can have multiple partitions and physical-property alternatives, so fifteen states does not mean fifteen complete plan evaluations.
The counts answer different questions. None is the exact number of useful physical plans after a database applies legality checks, properties, and pruning.
The living notebook
Explore the model
Interactive lab · cache
Subproblem reuse needs retained identities
Reset, set both C=4 and s=4, predict twelve hits in the initial sixteen fixed requests, then Play or Step. Separately Reset, set both C=3 and s=4, predict zero, then Play or Step. This four-address LRU cycle is only a memo-reuse analogy, with no join enumeration or physical-property state.
- Hits / requests
- 0 / 16
- Hit rate
- 0%
- Address-stream period
- 16 addresses
A fully associative LRU cache starts empty and requests address (i·s) mod 16. Hits move an address to the newest position; misses evict the oldest when full. Playback starts with 16 requests and adds two per second, capped at 4096 explicitly simulated requests. This toy stream is not a processor-cache benchmark. Parameter changes pause playback and recompute the model at the current elapsed time. Reset restores both parameters and returns time to zero. Playback starts paused. Adjust either parameter, then choose Play or Step.
Look forReusing state can avoid repeated work, but a real optimizer memo needs keys richer than the toy cached addresses.
Pause & reason
Check your understanding
Your turn
Try it yourself
Under the same unpruned ordered-tree convention, five labeled inputs have Catalan number C4=14. Count fixed-shape leaf permutations, all ordered bushy trees, and nonempty subsets.
Take a moment to make a prediction or work it out on paper. Open a hint when you need one.
Give me a hint
Use 5!, multiply by fourteen, and separately evaluate 2^5−1.
Compare with the solution
There are 120 fixed-shape leaf permutations, 120×14=1,680 ordered bushy trees, and 31 nonempty subsets. These are combinatorial teaching counts before semantic and connectivity restrictions. The subset count does not include its possible partitions, physical methods, orders, or parameterized alternatives.
Keep the idea
Take it with you
- A search-space count requires an explicit tree and equivalence convention.
- Subproblem reuse must preserve physical properties and semantic legality.
- Heuristic and constrained search trade planning work against modeled plan quality.
Read further
Original sources and deeper explanations to follow at your own pace.
Optional progress, saved in this browser when available. Revisit any lesson at any time.
Lesson not marked complete.