Skip to content

Commit d3b10a3

Browse files
Backport #89652 to 25.10: Add runtime filters only for supported join algorithms
1 parent 045eb28 commit d3b10a3

File tree

5 files changed

+29
-1
lines changed

5 files changed

+29
-1
lines changed

src/Processors/QueryPlan/JoinStepLogical.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class JoinStepLogical final : public IQueryPlanStep
8484

8585
const SortingStep::Settings & getSortingSettings() const { return sorting_settings; }
8686
const JoinSettings & getJoinSettings() const { return join_settings; }
87+
JoinSettings & getJoinSettings() { return join_settings; }
8788
const JoinOperator & getJoinOperator() const { return join_operator; }
8889
JoinOperator & getJoinOperator() { return join_operator; }
8990

src/Processors/QueryPlan/Optimizations/joinRuntimeFilter.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ const ActionsDAG::Node & createRuntimeFilterCondition(ActionsDAG & actions_dag,
4444
return condition;
4545
}
4646

47+
static bool supportsRuntimeFilter(JoinAlgorithm join_algorithm)
48+
{
49+
/// Runtime filter can only be applied to join algorithms that first read the right side and only after that read the left side.
50+
return
51+
join_algorithm == JoinAlgorithm::HASH ||
52+
join_algorithm == JoinAlgorithm::PARALLEL_HASH;
53+
}
54+
4755
bool tryAddJoinRuntimeFilter(QueryPlan::Node & node, QueryPlan::Nodes & nodes, const QueryPlanOptimizationSettings & optimization_settings)
4856
{
4957
/// Is this a join step?
@@ -57,12 +65,14 @@ bool tryAddJoinRuntimeFilter(QueryPlan::Node & node, QueryPlan::Nodes & nodes, c
5765

5866
/// Check if join can do runtime filtering on left table
5967
const auto & join_operator = join_step->getJoinOperator();
68+
auto & join_algorithms = join_step->getJoinSettings().join_algorithms;
6069
const bool can_use_runtime_filter =
6170
(
6271
(join_operator.kind == JoinKind::Inner && (join_operator.strictness == JoinStrictness::All || join_operator.strictness == JoinStrictness::Any)) ||
6372
((join_operator.kind == JoinKind::Left || join_operator.kind == JoinKind::Right) && join_operator.strictness == JoinStrictness::Semi)
6473
) &&
65-
(join_operator.locality == JoinLocality::Unspecified || join_operator.locality == JoinLocality::Local);
74+
(join_operator.locality == JoinLocality::Unspecified || join_operator.locality == JoinLocality::Local) &&
75+
std::find_if(join_algorithms.begin(), join_algorithms.end(), supportsRuntimeFilter) != join_algorithms.end();
6676

6777
if (!can_use_runtime_filter)
6878
return false;
@@ -183,6 +193,9 @@ bool tryAddJoinRuntimeFilter(QueryPlan::Node & node, QueryPlan::Nodes & nodes, c
183193

184194
node.children = {apply_filter_node, build_filter_node};
185195

196+
/// Remove algorithms that are not compatible with runtime filters
197+
std::erase_if(join_algorithms, [](auto join_algorithm) { return !supportsRuntimeFilter(join_algorithm); });
198+
186199
return true;
187200
}
188201

tests/queries/0_stateless/03580_join_runtime_filter.reference

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
500
99
6000
1010
6000
11+
Algorithm: FullSortingMergeJoin
1112
Filter column: and(__filterContains(_runtime_filter_UNIQ_ID_0, __table1.c_nationkey), __filterContains(_runtime_filter_UNIQ_ID_1, modulo(__table1.c_custkey, 100_UInt8))) (removed)
1213
BuildRuntimeFilter (Build runtime join filter on modulo(__table2.n_nationkey, 10_UInt8) (_runtime_filter_UNIQ_ID_1))
1314
BuildRuntimeFilter (Build runtime join filter on __table2.n_nationkey (_runtime_filter_UNIQ_ID_0))

tests/queries/0_stateless/03580_join_runtime_filter.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ INSERT INTO orders SELECT number, number/10000, number%1000 FROM numbers(1000000
1515
SET enable_analyzer=1;
1616
SET enable_join_runtime_filters=1;
1717
SET enable_parallel_replicas=0;
18+
SET join_algorithm = 'hash,parallel_hash';
1819

1920
SELECT avg(o_totalprice)
2021
FROM orders, customer, nation
@@ -73,6 +74,17 @@ FROM customer, nation
7374
WHERE c_nationkey = n_nationkey AND n_name = 'FRANCE'
7475
SETTINGS enable_join_runtime_filters = 1, join_runtime_bloom_filter_bytes = 4096, join_runtime_bloom_filter_hash_functions = 2;
7576

77+
-- Join algorithm that doesn't support runtime filters
78+
SELECT REGEXP_REPLACE(trimLeft(explain), '_runtime_filter_\\d+', '_runtime_filter_UNIQ_ID')
79+
FROM (
80+
EXPLAIN actions=1
81+
SELECT count()
82+
FROM customer, nation
83+
WHERE c_nationkey = n_nationkey AND n_nationkey%10 = c_custkey%100
84+
SETTINGS query_plan_join_swap_table=0, join_algorithm='full_sorting_merge'
85+
)
86+
WHERE (explain ILIKE '%Filter column%') OR (explain LIKE '%BuildRuntimeFilter%') OR (explain LIKE '%FullSorting%');
87+
7688
-- Filters on multiple join predicates
7789
SELECT REGEXP_REPLACE(trimLeft(explain), '_runtime_filter_\\d+', '_runtime_filter_UNIQ_ID')
7890
FROM (

tests/queries/0_stateless/03580_join_runtime_filter_prewhere.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ INSERT INTO customer SELECT number, 5 FROM numbers(500);
77

88
SET enable_analyzer=1;
99
SET enable_parallel_replicas=0;
10+
SET join_algorithm = 'hash,parallel_hash';
1011

1112
SELECT '-- Check that filter on c_nationkey is moved to PREWHERE';
1213
SELECT REGEXP_REPLACE(trimLeft(explain), '_runtime_filter_\\d+', '_runtime_filter_UNIQ_ID')

0 commit comments

Comments
 (0)