ADMS '26 · VLDB 2026 · GPU query processing

Rubberband

Memory-elastic, skew-tolerant GPU hash joins

Hangdong Zhao · Rathijit Sen · Craig Peeper · Matteo Interlandi

Microsoft Azure Data · Gray Systems Lab

The baseline

Open addressing is the default for CPU hash joins—and is becoming the go-to design for GPU hash joins too.

Build phase

h(t) = 8, so t starts at slot 8.

th(t) = 8 uh(u) = 1 w₁h(w) = 2 w₂h(w) = 2 v₁h(v) = 7 v₂h(v) = 7 v₃h(v) = 7 v₄h(v) = 7
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
insertion path
Press Insert or Enter

Shortcoming 1

Skew makes both build and probe more expensive.

Rows can be interleaved in memory without sharing a probe path.

as the shared path grows
Build more CAS attempts
Probe more scattered reads
0
u1
w₁2
3
w₂4
5
6
v₁7
t8
v₂9
10
v₃11
12
v₄13
14
15
16
w chain2 → 4 v probe sequence7 → 9 → 11 → 13 → ∅15 tslot 8 · skipped

Shortcoming 2

Open addressing lacks memory elasticity.

The table is hard to shrink when HBM gets tight.

shrinking H by fudge factor risks a collision cliff
0
u1
w₁2
3
w₂4
5
6
v₁7
t8
v₂9
10
v₃11
12
v₄13
14
15
16
all 17 slots remain resident
Other DBMS components contend for HBM H stays fixed at 17

Introducing Rubberband

Two new ingredients,
co-designed.

01
Logical rewrite

Equality hoisting

02
Physical layout

CSR-style hash-table layout

Idea 1 · equality hoisting

The hash-index resolution can be relaxed.

Exact lookup

hash join x = y
A.xB.y
hoist

Approximate lookup

post-filterx = y
bucket join φ(x) = φ(y)
A.xB.y
A ⋈x=y B σx=y(A ⋈φ(x)=φ(y) B)
φ(v) = v A.x = B.y
Hash join
φ ≡ 1 σx=y(A × B)
Nested loop join
φ(v) = hash(v) mod K flexible lookup resolution
Our tunable embedding

CSR stores rows densely.

Offsets mark contiguous buckets.

Dense rowIds

offsets
00 11 22 43 84 85
rowIds
t0
u1
w₁2
w₂3
v₁4
v₂5
v₃6
v₄7
N = 8 · no empty slots

Shrink K by removing boundaries.

Rows stay fixed. Buckets merge.

K: 5 → 3 · rows fixed

offsets
00 11 42 83
rowIds
t0
u×1
w₁2
w₂3
v₁4
v₂5
v₃6
v₄7
same 8 rows · 6 → 4 offsets
Count

Two arrays, zeroed. Count one row per click.

tb0 ub1 w₁b2 w₂b2 v₁b3 v₂b3 v₃b3 v₄b3
count 0 / 8

offsets K + 1 = 6

0[0]
0[1]
0[2]
0[3]
0[4]
0[5]

rowIds N = 8

0
1
2
3
4
5
6
7
1countatomicAdd per row 2scansame buffer, new meaning 3scatteratomicAdd returns the slot
Probe

Probe key v. One hash locates the bucket.

probe key v φ(v) = h(v) mod 5 = 3
0 / 6

offsets

0[0]
1[1]
2[2]
4[3]
8[4]
8[5]

rowIds

t0
u1
w₁2
w₂3
v₁4
v₂5
v₃6
v₄7
read path
Press Hash or Enter

Recap

same exact output v₁ · v₂ · v₃ · v₄

Open addressing

slots 7–15
Final open-addressing probe path across slots 7, 9, 11, 13, and empty slot 15
Scattered probe 7 → 9 → 11 → 13 → empty 15

Rubberband

offsets + rowIds
Final Rubberband probe with offsets 4 and 8 framing row IDs 4 through 7
Contiguous probe offsets 4 and 8 frame rowIds[4, 8)
Open addressing checks occupancy Rubberband checks bucket boundaries

Experiments

Memory elasticity

TPC-H SF100 22 full queries

Skew tolerance

Production skewed workloads

H100 NVL94 GB HBM3 · CUDA 12.8 Production engineMicrosoft CoddSpeed · SIGMOD'26 Industry Best Paper Median of 5runs after warm-up

TPC-H SF100 · orders ⋈ lineitem

150M build × 600M probe · build + probe runtime

TPC-H SF100 · 22-query aggregate

GPU execution as the bucket budget tightens

TPC-H SF100 · 6 PK–FK joins

Build, probe, and end-to-end speedup vs open addressing

Speedup vs OA · log
Default K / N = 1.05 47–57% of OA table
Tightened HBM K / N = 0.15 24–29% of OA table

TPC-H SF100 · 22 full queries

Peak intermediate HBM and end-to-end runtime · K / N = 1.05

* Join-heavy · hash table dominates peak HBM

11 production join captures

#0–2 mostly distinct · #3–10 duplicate-heavy

Speedup vs OA · log
Default K / N = 1.05 ≈50% of OA table
Tightened HBM K / N = 0.15 ≈25% of OA table

Production capture #11

One key owns 55% of the build.

12.5M build rows · speedup over open addressing

Build-key distribution 12.5M rows
vhot key · 55% all other keys · 45%
Default K / N = 1.05 ≈50% of OA table
435×Build 1,048×Probe 722×End-to-end

Two structural reasons

Why does Rubberband work so well under skew?

01 Regularize the hot path.

Retrying CAS and scattered chain walks become first-try adds and one contiguous scan.

Open addressing CAS + scattered chains
Build
CAS

Retries pile onto the hot slot.

Probe
v···v···v···v

Each probe re-walks a long random chain.

Rubberband add + contiguous scan
Build
+1

Every atomicAdd commits first try.

Probe
K = 6 7 offsets
offsets
0666666
rowIds
vvvvvv
scan [0, 6)

One cooperative, bandwidth-bound scan.

Summary

Rubberband:
Memory-Elastic, Skew-Tolerant GPU Hash Joins

  1. Equality hoisting. Join on buckets, post-filter x = y.
  2. Elastic CSR-style layout. Less HBM, more false positives.

Thank you

Microsoft Azure Data · Gray Systems Lab