Skip to content

Commit f7bf416

Browse files
committed
Improve doc
1 parent e3b8172 commit f7bf416

3 files changed

Lines changed: 13 additions & 28 deletions

File tree

datafusion/physical-plan/src/joins/hash_join/exec.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ pub(super) struct JoinLeftData {
217217
/// Shared atomic flag indicating if any probe partition saw NULL in join keys (for null-aware anti joins)
218218
pub(super) probe_side_has_null: AtomicBool,
219219
/// `true` if any hash bucket holds build rows with differing join keys
220-
/// (real hash collisions). When `false`, every chain is "pure" and the
220+
/// (hash collisions). When `false`, every chain is "pure" and the
221221
/// probe side can validate a chain with a single key check at its head
222222
/// instead of re-checking every duplicate. Computed once at build time.
223223
has_key_collisions: bool,
@@ -2103,9 +2103,7 @@ async fn collect_left_input(
21032103
// Detect whether the build side has real hash collisions (a bucket with
21042104
// differing keys). When it doesn't, the probe side can validate each chain
21052105
// with a single key check at its head instead of re-checking every
2106-
// duplicate — a large win for high-fanout joins. The ArrayMap (perfect
2107-
// hash) never collides and never reaches the recheck path, so it is always
2108-
// collision-free here.
2106+
// duplicate.
21092107
let has_key_collisions = match &join_hash_map {
21102108
Map::HashMap(hashmap) => {
21112109
hashmap.has_key_collisions(&left_values, null_equality)?

datafusion/physical-plan/src/joins/hash_join/stream.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -448,10 +448,7 @@ pub(super) fn lookup_join_hashmap(
448448
let mut start = 0;
449449
while start < probes.len() {
450450
let probe_idx = probes[start];
451-
let mut end = start + 1;
452-
while end < probes.len() && probes[end] == probe_idx {
453-
end += 1;
454-
}
451+
let end = start + probes[start..].partition_point(|&p| p == probe_idx);
455452
if comparator.is_equal(builds[start] as usize, probe_idx as usize) {
456453
build_out.extend_from_slice(&builds[start..end]);
457454
probe_out.extend_from_slice(&probes[start..end]);

datafusion/physical-plan/src/joins/join_hash_map.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -133,18 +133,9 @@ pub trait JoinHashMapType: Send + Sync {
133133
match_indices: &mut Vec<u64>,
134134
) -> Option<MapOffset>;
135135

136-
/// Detects whether any hash bucket holds build rows with differing join
137-
/// keys — i.e. real hash collisions.
138-
///
139-
/// Returns `false` only when every chain is "pure": all rows sharing a
140-
/// bucket also share the same join key. In that case the probe side can
141-
/// check the key once per chain head and emit the rest of the chain
142-
/// without re-checking each duplicate (see `lookup_join_hashmap`). When
143-
/// `true`, callers must fall back to a per-pair recheck.
144-
///
145-
/// `left_values` are the build-side join key columns. The default is the
146-
/// conservative `true` (always recheck); the concrete chained maps
147-
/// override it with an O(build_rows) scan.
136+
/// Returns `true` if any bucket holds build rows with differing join keys
137+
/// (real hash collisions). When `false`, the probe can check once per
138+
/// chain head and accept the whole run. Scanned once at build time.
148139
fn has_key_collisions(
149140
&self,
150141
left_values: &[ArrayRef],
@@ -530,15 +521,14 @@ pub fn contain_hashes<T>(map: &HashTable<(u64, T)>, hash_values: &[u64]) -> Bool
530521
BooleanArray::new(buffer, None)
531522
}
532523

533-
/// Scans the collision chain to detect whether any bucket holds rows with
534-
/// differing join keys (real hash collisions).
524+
/// Scans the `next` chain to detect real hash collisions (two build rows in
525+
/// the same bucket with different keys). `next[i]` stores `prev_row + 1`
526+
/// (`0` = end of chain). Checking every adjacent linked pair is sufficient:
527+
/// any two distinct keys in the same bucket must appear as neighbors somewhere.
535528
///
536-
/// Each entry of `next` links a build row to the previous row inserted into
537-
/// the same bucket (`next[i]` stores `prev_row + 1`, `0` marks the end of a
538-
/// chain). Two rows joined by a link share a hash, so comparing the keys
539-
/// across every link covers every chain: if all linked pairs are equal, no
540-
/// bucket mixes keys and the map is collision-free. Returns `true` on the
541-
/// first differing link. O(build_rows) comparisons, run once at build time.
529+
/// Example — keys `["cat", "cat", "dog"]`, next `[0, 1, 2]`:
530+
/// row 1 → prev 0: "cat"=="cat" ✓
531+
/// row 2 → prev 1: "dog"!="cat" → return true (collision found)
542532
fn detect_key_collisions<T>(
543533
next: &[T],
544534
left_values: &[ArrayRef],

0 commit comments

Comments
 (0)