Skip to content

[VL] Reuse driver-built broadcast hash tables across queries - #12872

Draft
zhouyuan wants to merge 1 commit into
apache:mainfrom
zhouyuan:driver-broadcast-hashtable-cache
Draft

[VL] Reuse driver-built broadcast hash tables across queries#12872
zhouyuan wants to merge 1 commit into
apache:mainfrom
zhouyuan:driver-broadcast-hashtable-cache

Conversation

@zhouyuan

Copy link
Copy Markdown
Member

What changes are proposed in this pull request?

Driver-side broadcast hash table build already caches the serialized hash table, but it keys the cache by the BroadcastExchangeExec instance, so the entry can only be reused by exchange reuse inside one query. Workloads that run the same queries over and over, e.g. the concurrent streams of a TPC-DS throughput run, collect, build, serialize and broadcast the very same hash table again for every query.

Add a driver-side cache that keys the built relation by the canonicalized build side plan plus everything the content of the hash table depends on: the normalized build keys, the build schema, the substrait join type, the build side, the filter build column ordinals, the null aware / existence join flags, the bloom filter pushdown size and whether duplicates were dropped. Expression ids are normalized against the build side output, so two instances of the same query map to the same key.

The lookup happens before the build side is collected, so a hit skips the collect job, the hash table build and the serialization, and replays the row count and data size of the job that built the relation into the exchange metrics. When the very same relation object is broadcast again, the broadcast created the first time is handed out as well, which also skips re-serializing and re-uploading the blocks.

Build sides with non-deterministic expressions or subqueries, including the runtime filters of dynamic partition pruning, are never shared. Reuse assumes the data behind a build side does not change while the application is running, and cached relations hold driver memory until they are evicted, so the cache is off by default and bounded by size:

spark.gluten.sql.columnar.backend.velox.driverSideBroadcastHashTableCache.enabled
spark.gluten.sql.columnar.backend.velox.driverSideBroadcastHashTableCache.maxSize

How was this patch tested?

new tests

Was this patch authored or co-authored using generative AI tooling?

Claude Opus
IBM Bob

Driver-side broadcast hash table build already caches the serialized hash
table, but it keys the cache by the BroadcastExchangeExec instance, so the
entry can only be reused by exchange reuse inside one query. Workloads that
run the same queries over and over, e.g. the concurrent streams of a TPC-DS
throughput run, collect, build, serialize and broadcast the very same hash
table again for every query.

Add a driver-side cache that keys the built relation by the canonicalized
build side plan plus everything the content of the hash table depends on:
the normalized build keys, the build schema, the substrait join type, the
build side, the filter build column ordinals, the null aware / existence
join flags, the bloom filter pushdown size and whether duplicates were
dropped. Expression ids are normalized against the build side output, so
two instances of the same query map to the same key.

The lookup happens before the build side is collected, so a hit skips the
collect job, the hash table build and the serialization, and replays the
row count and data size of the job that built the relation into the
exchange metrics. When the very same relation object is broadcast again,
the broadcast created the first time is handed out as well, which also
skips re-serializing and re-uploading the blocks.

Build sides with non-deterministic expressions or subqueries, including the
runtime filters of dynamic partition pruning, are never shared. Reuse
assumes the data behind a build side does not change while the application
is running, and cached relations hold driver memory until they are evicted,
so the cache is off by default and bounded by size:

  spark.gluten.sql.columnar.backend.velox.driverSideBroadcastHashTableCache.enabled
  spark.gluten.sql.columnar.backend.velox.driverSideBroadcastHashTableCache.maxSize
@github-actions github-actions Bot added CORE works for Gluten Core VELOX DOCS labels Aug 24, 2026
@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI on x86

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CORE works for Gluten Core DOCS VELOX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant