java-topology/defects/flink/patch/flink-0003-aggregatereducegroupingrule-newgroupinglist-hashset.md

1.4 KiB
Raw Blame History

UNDF: UNDF-2026-000000396

flink-0003: AggregateReduceGroupingRule — List.contains() inside for loop

Defect ID

flink-0003

File:Line

flink-table/flink-table-planner/src/main/java/org/apache/flink/table/planner/plan/rules/logical/AggregateReduceGroupingRule.java:88

Description

In onMatch():

List<Integer> newGroupingList = newGrouping.toList();  // List<Integer>
for (int column : originalGrouping) {                  // O(G) iterations
    if (newGroupingList.contains(column)) {            // O(G) linear scan each time
        ...
    }
}

newGroupingList is a List<Integer>. Each .contains() call does a linear scan O(G) where G = number of grouping columns. Total: O(G²).

This fires during query planning on every aggregate that has reducible grouping keys — i.e., every GROUP BY with functional dependencies. In queries with wide GROUP BY clauses (e.g., 50+ columns in analytics), this is O(2500) instead of O(50).

Complexity

  • Slow: O(G²) — List.contains() = O(G)
  • Fast: O(G) — HashSet.contains() = O(1)

Severity

MEDIUM

Speedup Estimate

~G× improvement; at G=50 grouping columns, ~50x speedup in the planning phase.

Fix

Replace newGroupingList with Set<Integer> newGroupingSet = new HashSet<>(newGrouping.toList()). The list is only used for .contains() and .size() — both work identically on HashSet.