Skip to main content

JoinHashTable

Struct JoinHashTable 

Source
pub struct JoinHashTable { /* private fields */ }
Expand description

Optimized hash table for join operations.

This hash table is specifically designed for the build phase of hash joins. It uses chaining with linked entries stored in a flat vector for cache efficiency.

§Example

// Build phase
let mut table = JoinHashTable::with_capacity(build_rows.len());
for (idx, row) in build_rows.iter().enumerate() {
    let hash = hash_row_keys(row, &key_indices);
    table.insert(hash, idx as u32);
}

// Probe phase
for probe_row in probe_rows {
    let hash = hash_row_keys(probe_row, &probe_key_indices);
    for build_idx in table.probe(hash) {
        // Verify actual key equality and produce output
    }
}

Implementations§

Source§

impl JoinHashTable

Source

pub fn estimated_retained_bytes(row_count: usize) -> Option<usize>

Exact retained size of bucket heads and compact entries before Vec allocator rounding. Overflow or row indices outside u32 are rejected.

Source

pub fn fits_retained_budget(row_count: usize, max_bytes: usize) -> bool

Source

pub fn with_capacity(row_count: usize) -> Self

Create a new hash table with capacity for the given number of rows.

The table is pre-allocated to avoid resizing during build. Bucket count is sized to achieve ~75% load factor.

Source

pub fn empty() -> Self

Create an empty hash table (for cases where build side is empty).

Source

pub fn build(rows: &[Row], key_indices: &[usize]) -> Self

Build a hash table from rows using the specified key indices.

This is the main entry point for creating a join hash table.

Source

pub fn build_with_observer( rows: &[Row], key_indices: &[usize], observer: &mut impl JoinHashObserver, ) -> Self

Build hash table and populate bloom filter in a single pass.

This is more efficient than building separately because we only extract and hash key values once for both structures.

§Arguments
  • rows - Build side rows
  • key_indices - Indices of join key columns
  • bloom_builder - Bloom filter builder to populate
§Returns

The built hash table (bloom filter is populated in-place)

Source

pub fn insert(&mut self, hash: u64, row_idx: u32)

Insert a row index with its pre-computed hash.

§Arguments
  • hash - The hash of the row’s key columns
  • row_idx - The index of the row in the build rows vector
Source

pub fn probe(&self, hash: u64) -> ProbeIter<'_>

Probe the hash table for matching row indices.

Returns an iterator that yields row indices for entries with matching hashes. The caller must verify actual key equality for each returned index (to handle hash collisions).

This is a zero-allocation operation - the iterator only holds a reference to the table.

Source

pub fn probe_cursor(&self, hash: u64) -> ProbeCursor

Start a resumable zero-allocation probe. Unlike ProbeIter, the cursor owns no borrow and can therefore live inside a streaming operator while that operator mutates its other state between emitted matches.

Source

pub fn probe_next(&self, cursor: &mut ProbeCursor) -> Option<usize>

Advance one resumable probe and return the next matching row index.

Source

pub fn len(&self) -> usize

Get the number of entries in the table.

Source

pub fn is_empty(&self) -> bool

Check if the table is empty.

Source

pub fn bucket_count(&self) -> usize

Get the number of buckets.

Source

pub fn load_factor(&self) -> f64

Get the load factor (entries / buckets).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CompactArcDrop for T

Source§

unsafe fn drop_and_dealloc(ptr: *mut u8)

Drop the contained data and deallocate the header+data allocation. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V