28 lines
1.2 KiB
Diff
28 lines
1.2 KiB
Diff
# UNDF: UNDF-2026-000000765
|
||
# UNDF: (leave blank)
|
||
# DuckDB CWE-407: ComputeOverlappingBindings O(N×H) vector linear scan
|
||
# File: src/optimizer/build_probe_side_optimizer.cpp
|
||
# Severity: MEDIUM — optimizer hot path for join build/probe side selection
|
||
# Ratio: ~250x at N=H=500 column bindings (wide star-schema joins)
|
||
#
|
||
# The optimizer decides which side of a join to use as the build vs probe side.
|
||
# ComputeOverlappingBindings scans a haystack vector for each needle via std::find,
|
||
# yielding O(N×H). With wide tables (many columns), this becomes quadratic.
|
||
# Fix: convert haystack to unordered_set for O(1) lookup → O(N+H) total.
|
||
--- a/src/optimizer/build_probe_side_optimizer.cpp
|
||
+++ b/src/optimizer/build_probe_side_optimizer.cpp
|
||
@@ -88,11 +88,14 @@
|
||
}
|
||
|
||
+#include <unordered_set>
|
||
+
|
||
static inline idx_t ComputeOverlappingBindings(const vector<ColumnBinding> &haystack,
|
||
const vector<ColumnBinding> &needles) {
|
||
+ std::unordered_set<ColumnBinding, ColumnBindingHashFunction> haystack_set(haystack.begin(), haystack.end());
|
||
idx_t result = 0;
|
||
for (auto &needle : needles) {
|
||
- if (std::find(haystack.begin(), haystack.end(), needle) != haystack.end()) {
|
||
+ if (haystack_set.count(needle)) {
|
||
result++;
|
||
}
|
||
}
|