Expand description
Modern streaming JOIN executor using Volcano-style operators.
This module provides high-performance JOIN execution with:
- Hash Join: Build smaller side, probe larger side with O(N+M) complexity
- Merge Join: O(N+M) when inputs are pre-sorted on join keys
- Nested Loop: O(N*M) fallback for non-equality joins or small tables
- Early Termination: LIMIT stops execution immediately
- Residual Filters: Non-equality conditions applied during streaming
§Architecture
JoinRequest
│
▼
┌─────────────────────────────────┐
│ JoinExecutor::execute() │
│ 1. Analyze join condition │
│ 2. Select optimal algorithm │
│ 3. Execute with streaming │
│ 4. Early terminate at LIMIT │
└─────────────────────────────────┘
│
▼
JoinResult { rows, columns }§Design Decisions & Tradeoffs
§Hybrid Execution: Streaming vs Parallel
This executor uses a hybrid approach that dynamically chooses between Volcano-style streaming and parallel bulk processing based on query characteristics:
§Streaming Volcano Path (default for small datasets or small LIMIT)
- When: Build side < 10,000 rows OR LIMIT ≤ 1,000
- Benefits:
- O(1) memory for probe side (streaming, not materialized)
- Early termination: LIMIT 10 stops after 10 rows
- Low latency to first row (important for interactive queries)
- Composable operators (Filter → Join → Project → Limit)
§Parallel Hash Join Path (for large analytical queries)
- When: Build side ≥ 10,000 rows AND (no LIMIT or LIMIT > 1,000)
- Benefits:
- Parallel hash build using a pre-admitted fixed-width atomic table
- Parallel probe with Rayon work-stealing
- 2-4x speedup on multi-core systems for large joins
- Atomic tracking for OUTER join unmatched rows
§Why Not Always Parallel?
Parallel execution has overhead (task scheduling, synchronization). For:
- Small datasets: overhead exceeds benefit
- Small LIMIT: streaming stops early; parallel computes full result then truncates
§Merge Join Boundary
The binary entry point currently receives materialized relation batches,
but MergeJoinOperator itself consumes its certified ordered inputs one row
at a time. Only matching duplicate-key groups are blocking state, and their
owner is bounded before execution:
left ordered operator ┐
├→ bounded streaming MergeJoinOperator
right ordered operator ┘§Bloom Filter Optimization
Bloom filters can accelerate hash joins by filtering probe rows that definitely won’t match before touching the hash table. This is particularly effective for:
- High selectivity joins (few matches relative to probe size)
- Multi-way joins (filter cascades through the plan)
Query planning can build a runtime bloom filter and wrap the probe input in
BloomFilterOperator before handing it to the streaming join executor.
Structs§
- Join
Analysis - Analysis of a join operation for algorithm selection.
- Join
Executor - Modern streaming join executor.
- Join
Input Orderings - Physical ordering certificates for both sides of one JOIN edge.
- Join
Request - Request to execute a join operation.
- Join
Result - Result of a streaming join execution.
- Runtime
Join Decision - Runtime join decision produced by the planner and consumed by physical JOIN.
- Streaming
Join Request - Request to execute a streaming hash join.
Enums§
- Join
Rows - Runtime
Join Algorithm - Runtime join algorithm selection.