Skip to content

perf: use one null-aware mark join for hashable IN subqueries in projections - #25338

Open
adriangb wants to merge 15 commits into
apache:mainfrom
pydantic:in-exists-subquery-projection
Open

adriangb wants to merge 15 commits into
apache:mainfrom
pydantic:in-exists-subquery-projection

Conversation

@adriangb

@adriangb adriangb commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Which issue does this PR close?

This PR supersedes #21363 by @crm26. It reuses the single mark join approach from that PR, and @crm26 is a co-author of the main commit.

It also builds on #24972, which added the decorrelation of IN subqueries in a projection.

Rationale for this change

An IN or NOT IN subquery in a SELECT list gives correct results today, but the plan is quadratic. The optimizer builds three mark joins for each subquery. Two of them have no join predicate, so they run as nested loop joins over all outer rows and all inner rows. COALESCE duplicates the expression, so that shape gets six mark joins.

This PR keeps one hash mark join for each subquery when the join filter is hashable. The three join fallback stays only for a non-equality correlation (Q6 below), which is not changed by this PR and is tracked separately in #25336.

Shape Query main this PR Result rows identical
Q1 Bare IN in the SELECT list 190.730 s 0.034 s yes
Q2 COALESCE((x IN (...))::boolean, false) 351.579 s 0.054 s yes
Q3 Correlated IN with an equality predicate 1.372 s 0.091 s yes
Q4 Two IN subqueries in separate columns 296.676 s 0.063 s yes
Q5 Correlated EXISTS 0.021 s 0.021 s yes
Q6 Correlated IN with a non-equality predicate (fallback path, unchanged) 307.565 s 261.582 s yes

PR to add these as benchmarks: #25346

Reproduction with datafusion-cli: script, plans and timings for each shape

Run the script with datafusion-cli -f mre.sql. It creates two tables with 200000 rows each, then for each shape it prints EXPLAIN and runs the query. datafusion-cli prints the elapsed time after each statement. The numbers above come from one run of this script on an Apple Silicon laptop, main at 22651d2 and this PR built with cargo build -p datafusion-cli --profile ci. The result rows of every query are identical between the two builds.

SET datafusion.execution.target_partitions = 4;
CREATE TABLE outer_t AS SELECT CAST(v AS INT) AS id, CAST(v % 1000 AS INT) AS z FROM (SELECT unnest(generate_series(1, 200000)) AS v);
CREATE TABLE inner_t AS SELECT CASE WHEN v % 97 = 0 THEN NULL ELSE CAST(v * 2 AS INT) END AS id, CAST(v % 1000 AS INT) AS z FROM (SELECT unnest(generate_series(1, 200000)) AS v);
SELECT 'Q1' AS shape;
EXPLAIN SELECT id, id IN (SELECT id FROM inner_t) AS m FROM outer_t;
SELECT count(*) FILTER (WHERE m), count(*) FILTER (WHERE m IS NULL) FROM (SELECT id, id IN (SELECT id FROM inner_t) AS m FROM outer_t);
SELECT 'Q2' AS shape;
EXPLAIN SELECT id, COALESCE((id IN (SELECT id FROM inner_t))::boolean, false) AS m FROM outer_t;
SELECT count(*) FILTER (WHERE m) FROM (SELECT id, COALESCE((id IN (SELECT id FROM inner_t))::boolean, false) AS m FROM outer_t);
SELECT 'Q3' AS shape;
EXPLAIN SELECT id, id IN (SELECT i.id FROM inner_t i WHERE i.z = o.z) AS m FROM outer_t o;
SELECT count(*) FILTER (WHERE m), count(*) FILTER (WHERE m IS NULL) FROM (SELECT id, id IN (SELECT i.id FROM inner_t i WHERE i.z = o.z) AS m FROM outer_t o);
SELECT 'Q4' AS shape;
EXPLAIN SELECT id IN (SELECT id FROM inner_t) AS a, id IN (SELECT id FROM inner_t WHERE z < 500) AS b FROM outer_t;
SELECT count(*) FILTER (WHERE a), count(*) FILTER (WHERE b) FROM (SELECT id IN (SELECT id FROM inner_t) AS a, id IN (SELECT id FROM inner_t WHERE z < 500) AS b FROM outer_t);
SELECT 'Q5' AS shape;
EXPLAIN SELECT id, EXISTS (SELECT 1 FROM inner_t i WHERE i.id = o.id) AS e FROM outer_t o;
SELECT count(*) FILTER (WHERE e) FROM (SELECT id, EXISTS (SELECT 1 FROM inner_t i WHERE i.id = o.id) AS e FROM outer_t o);
SELECT 'Q6' AS shape;
EXPLAIN SELECT id, id IN (SELECT i.id FROM inner_t i WHERE i.z < o.z) AS m FROM outer_t o;
SELECT count(*) FILTER (WHERE m), count(*) FILTER (WHERE m IS NULL) FROM (SELECT id, id IN (SELECT i.id FROM inner_t i WHERE i.z < o.z) AS m FROM outer_t o);
Q1: Bare `IN` in the SELECT list, plans on main and on this PR

main, query time 190.730 s

logical_plan
Projection: outer_t.id, __correlated_sq_1.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_2.mark OR outer_t.id IS NULL AND __correlated_sq_3.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_1.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS m
  LeftMark Join:
    LeftMark Join:
      LeftMark Join: outer_t.id = __correlated_sq_1.id null_aware
        TableScan: outer_t projection=[id]
        SubqueryAlias: __correlated_sq_1
          TableScan: inner_t projection=[id]
      SubqueryAlias: __correlated_sq_2
        Filter: inner_t.id IS NULL
          TableScan: inner_t projection=[id]
    SubqueryAlias: __correlated_sq_3
      TableScan: inner_t projection=[id]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 IS NOT DISTINCT FROM true OR (mark@2 OR id@0 IS NULL AND mark@3) IS NOT DISTINCT FROM true AND mark@1 IS DISTINCT FROM true AND NULL as m]
  NestedLoopJoinExec: join_type=LeftMark
    CoalescePartitionsExec
      NestedLoopJoinExec: join_type=RightMark
        CoalescePartitionsExec
          FilterExec: id@0 IS NULL
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
          CoalescePartitionsExec
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

this PR, query time 0.034 s

logical_plan
Projection: outer_t.id, __correlated_sq_1.mark AS m
  LeftMark Join: outer_t.id = __correlated_sq_1.id null_aware
    TableScan: outer_t projection=[id]
    SubqueryAlias: __correlated_sq_1
      TableScan: inner_t projection=[id]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 as m]
  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
    CoalescePartitionsExec
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

Q2: `COALESCE((x IN (...))::boolean, false)`, plans on main and on this PR

main, query time 351.579 s

logical_plan
Projection: outer_t.id, CAST(__correlated_sq_1.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_2.mark OR outer_t.id IS NULL AND __correlated_sq_3.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_1.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS Boolean) IS NOT NULL AND CAST(__correlated_sq_4.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_5.mark OR outer_t.id IS NULL AND __correlated_sq_6.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_4.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS Boolean) AS m
  LeftMark Join:
    LeftMark Join:
      LeftMark Join: outer_t.id = __correlated_sq_4.id null_aware
        LeftMark Join:
          LeftMark Join:
            LeftMark Join: outer_t.id = __correlated_sq_1.id null_aware
              TableScan: outer_t projection=[id]
              SubqueryAlias: __correlated_sq_1
                TableScan: inner_t projection=[id]
            SubqueryAlias: __correlated_sq_2
              Filter: inner_t.id IS NULL
                TableScan: inner_t projection=[id]
          SubqueryAlias: __correlated_sq_3
            TableScan: inner_t projection=[id]
        SubqueryAlias: __correlated_sq_4
          TableScan: inner_t projection=[id]
      SubqueryAlias: __correlated_sq_5
        Filter: inner_t.id IS NULL
          TableScan: inner_t projection=[id]
    SubqueryAlias: __correlated_sq_6
      TableScan: inner_t projection=[id]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 IS NOT DISTINCT FROM true OR (mark@2 OR id@0 IS NULL AND mark@3) IS NOT DISTINCT FROM true AND mark@1 IS DISTINCT FROM true AND NULL IS NOT NULL AND (mark@4 IS NOT DISTINCT FROM true OR (mark@5 OR id@0 IS NULL AND mark@6) IS NOT DISTINCT FROM true AND mark@4 IS DISTINCT FROM true AND NULL) as m]
  NestedLoopJoinExec: join_type=LeftMark
    CoalescePartitionsExec
      NestedLoopJoinExec: join_type=RightMark
        CoalescePartitionsExec
          FilterExec: id@0 IS NULL
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
          CoalescePartitionsExec
            NestedLoopJoinExec: join_type=LeftMark
              CoalescePartitionsExec
                NestedLoopJoinExec: join_type=RightMark
                  CoalescePartitionsExec
                    FilterExec: id@0 IS NULL
                      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
                  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
                    CoalescePartitionsExec
                      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
                    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
              DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

this PR, query time 0.054 s

logical_plan
Projection: outer_t.id, CAST(__correlated_sq_1.mark AS Boolean) IS NOT NULL AND CAST(__correlated_sq_2.mark AS Boolean) AS m
  LeftMark Join: outer_t.id = __correlated_sq_2.id null_aware
    LeftMark Join: outer_t.id = __correlated_sq_1.id null_aware
      TableScan: outer_t projection=[id]
      SubqueryAlias: __correlated_sq_1
        TableScan: inner_t projection=[id]
    SubqueryAlias: __correlated_sq_2
      TableScan: inner_t projection=[id]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 IS NOT NULL AND mark@2 as m]
  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
    CoalescePartitionsExec
      HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
        CoalescePartitionsExec
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

Q3: Correlated `IN` with an equality predicate, plans on main and on this PR

main, query time 1.372 s

logical_plan
Projection: o.id, __correlated_sq_1.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_2.mark OR o.id IS NULL AND __correlated_sq_3.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_1.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS m
  LeftMark Join: o.z = __correlated_sq_3.z
    LeftMark Join: o.z = __correlated_sq_2.z
      LeftMark Join: o.id = __correlated_sq_1.id, o.z = __correlated_sq_1.z null_aware
        SubqueryAlias: o
          TableScan: outer_t projection=[id, z]
        SubqueryAlias: __correlated_sq_1
          SubqueryAlias: i
            TableScan: inner_t projection=[id, z]
      SubqueryAlias: __correlated_sq_2
        SubqueryAlias: i
          Projection: inner_t.z
            Filter: inner_t.id IS NULL
              TableScan: inner_t projection=[id, z]
    SubqueryAlias: __correlated_sq_3
      SubqueryAlias: i
        TableScan: inner_t projection=[z]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 IS NOT DISTINCT FROM true OR (mark@2 OR id@0 IS NULL AND mark@3) IS NOT DISTINCT FROM true AND mark@1 IS DISTINCT FROM true AND NULL as m]
  HashJoinExec: mode=CollectLeft, join_type=RightMark, on=[(z@0, z@1)], projection=[id@0, mark@2, mark@3, mark@4]
    CoalescePartitionsExec
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    HashJoinExec: mode=CollectLeft, join_type=RightMark, on=[(z@0, z@1)]
      CoalescePartitionsExec
        FilterExec: id@0 IS NULL, projection=[z@1]
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
      HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0), (z@1, z@1)], null_aware
        CoalescePartitionsExec
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

this PR, query time 0.091 s

logical_plan
Projection: o.id, __correlated_sq_1.mark AS m
  LeftMark Join: o.id = __correlated_sq_1.id, o.z = __correlated_sq_1.z null_aware
    SubqueryAlias: o
      TableScan: outer_t projection=[id, z]
    SubqueryAlias: __correlated_sq_1
      SubqueryAlias: i
        TableScan: inner_t projection=[id, z]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 as m]
  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0), (z@1, z@1)], projection=[id@0, mark@2], null_aware
    CoalescePartitionsExec
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

Q4: Two `IN` subqueries in separate columns, plans on main and on this PR

main, query time 296.676 s

logical_plan
Projection: __correlated_sq_1.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_2.mark OR outer_t.id IS NULL AND __correlated_sq_3.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_1.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS a, __correlated_sq_4.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_5.mark OR outer_t.id IS NULL AND __correlated_sq_6.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_4.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS b
  LeftMark Join:
    LeftMark Join:
      LeftMark Join: outer_t.id = __correlated_sq_4.id null_aware
        LeftMark Join:
          LeftMark Join:
            LeftMark Join: outer_t.id = __correlated_sq_1.id null_aware
              TableScan: outer_t projection=[id]
              SubqueryAlias: __correlated_sq_1
                TableScan: inner_t projection=[id]
            SubqueryAlias: __correlated_sq_2
              Filter: inner_t.id IS NULL
                TableScan: inner_t projection=[id]
          SubqueryAlias: __correlated_sq_3
            TableScan: inner_t projection=[id]
        SubqueryAlias: __correlated_sq_4
          Projection: inner_t.id
            Filter: inner_t.z < Int32(500)
              TableScan: inner_t projection=[id, z]
      SubqueryAlias: __correlated_sq_5
        Projection: inner_t.id
          Filter: inner_t.z < Int32(500) AND inner_t.id IS NULL
            TableScan: inner_t projection=[id, z]
    SubqueryAlias: __correlated_sq_6
      Projection: inner_t.id
        Filter: inner_t.z < Int32(500)
          TableScan: inner_t projection=[id, z]
physical_plan
ProjectionExec: expr=[mark@1 IS NOT DISTINCT FROM true OR (mark@2 OR id@0 IS NULL AND mark@3) IS NOT DISTINCT FROM true AND mark@1 IS DISTINCT FROM true AND NULL as a, mark@4 IS NOT DISTINCT FROM true OR (mark@5 OR id@0 IS NULL AND mark@6) IS NOT DISTINCT FROM true AND mark@4 IS DISTINCT FROM true AND NULL as b]
  NestedLoopJoinExec: join_type=LeftMark
    CoalescePartitionsExec
      NestedLoopJoinExec: join_type=RightMark
        CoalescePartitionsExec
          FilterExec: z@1 < 500 AND id@0 IS NULL, projection=[id@0]
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
          CoalescePartitionsExec
            NestedLoopJoinExec: join_type=LeftMark
              CoalescePartitionsExec
                NestedLoopJoinExec: join_type=RightMark
                  CoalescePartitionsExec
                    FilterExec: id@0 IS NULL
                      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
                  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
                    CoalescePartitionsExec
                      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
                    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
              DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
          FilterExec: z@1 < 500, projection=[id@0]
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    FilterExec: z@1 < 500, projection=[id@0]
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

this PR, query time 0.063 s

logical_plan
Projection: __correlated_sq_1.mark AS a, __correlated_sq_2.mark AS b
  LeftMark Join: outer_t.id = __correlated_sq_2.id null_aware
    LeftMark Join: outer_t.id = __correlated_sq_1.id null_aware
      TableScan: outer_t projection=[id]
      SubqueryAlias: __correlated_sq_1
        TableScan: inner_t projection=[id]
    SubqueryAlias: __correlated_sq_2
      Projection: inner_t.id
        Filter: inner_t.z < Int32(500)
          TableScan: inner_t projection=[id, z]
physical_plan
ProjectionExec: expr=[mark@0 as a, mark@1 as b]
  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], projection=[mark@1, mark@2], null_aware
    CoalescePartitionsExec
      HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], null_aware
        CoalescePartitionsExec
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    FilterExec: z@1 < 500, projection=[id@0]
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

Q5: Correlated `EXISTS`, plans on main and on this PR

main, query time 0.021 s

logical_plan
Projection: o.id, __correlated_sq_1.mark AS e
  LeftMark Join: o.id = __correlated_sq_1.id
    SubqueryAlias: o
      TableScan: outer_t projection=[id]
    SubqueryAlias: __correlated_sq_1
      SubqueryAlias: i
        TableScan: inner_t projection=[id]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 as e]
  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)]
    CoalescePartitionsExec
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

this PR, query time 0.021 s

logical_plan
Projection: o.id, __correlated_sq_1.mark AS e
  LeftMark Join: o.id = __correlated_sq_1.id
    SubqueryAlias: o
      TableScan: outer_t projection=[id]
    SubqueryAlias: __correlated_sq_1
      SubqueryAlias: i
        TableScan: inner_t projection=[id]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 as e]
  HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)]
    CoalescePartitionsExec
      DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

Q6: Correlated `IN` with a non-equality predicate (fallback path, unchanged), plans on main and on this PR

main, query time 307.565 s

logical_plan
Projection: o.id, __correlated_sq_1.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_2.mark OR o.id IS NULL AND __correlated_sq_3.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_1.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS m
  LeftMark Join:  Filter: __correlated_sq_3.z < o.z
    LeftMark Join:  Filter: __correlated_sq_2.z < o.z
      LeftMark Join: o.id = __correlated_sq_1.id Filter: __correlated_sq_1.z < o.z
        SubqueryAlias: o
          TableScan: outer_t projection=[id, z]
        SubqueryAlias: __correlated_sq_1
          SubqueryAlias: i
            TableScan: inner_t projection=[id, z]
      SubqueryAlias: __correlated_sq_2
        SubqueryAlias: i
          Projection: inner_t.z
            Filter: inner_t.id IS NULL
              TableScan: inner_t projection=[id, z]
    SubqueryAlias: __correlated_sq_3
      SubqueryAlias: i
        TableScan: inner_t projection=[z]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 IS NOT DISTINCT FROM true OR (mark@2 OR id@0 IS NULL AND mark@3) IS NOT DISTINCT FROM true AND mark@1 IS DISTINCT FROM true AND NULL as m]
  NestedLoopJoinExec: join_type=LeftMark, filter=z@1 < z@0, projection=[id@0, mark@2, mark@3, mark@4]
    CoalescePartitionsExec
      NestedLoopJoinExec: join_type=RightMark, filter=z@1 < z@0
        CoalescePartitionsExec
          FilterExec: id@0 IS NULL, projection=[z@1]
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], filter=z@1 < z@0
          CoalescePartitionsExec
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

this PR, query time 261.582 s

logical_plan
Projection: o.id, __correlated_sq_1.mark IS NOT DISTINCT FROM Boolean(true) OR (__correlated_sq_2.mark OR o.id IS NULL AND __correlated_sq_3.mark) IS NOT DISTINCT FROM Boolean(true) AND __correlated_sq_1.mark IS DISTINCT FROM Boolean(true) AND Boolean(NULL) AS m
  LeftMark Join:  Filter: __correlated_sq_3.z < o.z
    LeftMark Join:  Filter: __correlated_sq_2.z < o.z
      LeftMark Join: o.id = __correlated_sq_1.id Filter: __correlated_sq_1.z < o.z
        SubqueryAlias: o
          TableScan: outer_t projection=[id, z]
        SubqueryAlias: __correlated_sq_1
          SubqueryAlias: i
            TableScan: inner_t projection=[id, z]
      SubqueryAlias: __correlated_sq_2
        SubqueryAlias: i
          Projection: inner_t.z
            Filter: inner_t.id IS NULL
              TableScan: inner_t projection=[id, z]
    SubqueryAlias: __correlated_sq_3
      SubqueryAlias: i
        TableScan: inner_t projection=[z]
physical_plan
ProjectionExec: expr=[id@0 as id, mark@1 IS NOT DISTINCT FROM true OR (mark@2 OR id@0 IS NULL AND mark@3) IS NOT DISTINCT FROM true AND mark@1 IS DISTINCT FROM true AND NULL as m]
  NestedLoopJoinExec: join_type=LeftMark, filter=z@1 < z@0, projection=[id@0, mark@2, mark@3, mark@4]
    CoalescePartitionsExec
      NestedLoopJoinExec: join_type=RightMark, filter=z@1 < z@0
        CoalescePartitionsExec
          FilterExec: id@0 IS NULL, projection=[z@1]
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
        HashJoinExec: mode=CollectLeft, join_type=LeftMark, on=[(id@0, id@0)], filter=z@1 < z@0
          CoalescePartitionsExec
            DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
          DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]
    DataSourceExec: partitions=4, partition_sizes=[7, 6, 6, 6]

What changes are included in this PR?

  1. build_join now reports whether the mark column of the LeftMark join is exact under three-valued logic. It is exact when the join filter is hashable only. The join is null aware when the keys can be NULL.

  2. in_subquery_value_mark_join in datafusion/optimizer/src/decorrelate_predicate_subquery.rs now builds the matched join first. If that join is exact, it returns the mark column alone, or NOT mark for NOT IN. The three join materialization is kept only when a residual non-equality filter remains, because the hash join cannot mark UNKNOWN for a residual predicate.

  3. The regression test for fix: scan subqueries when advancing the extracted-alias generator #24574 in projection_pushdown.slt now uses a correlated subquery with LIMIT 1. The subquery then still reaches ExtractLeafExpressions, and the alias generator still starts at 2 inside it. The earlier version of the test let the subquery be flattened, so it no longer exercised the scan inside a subquery path.

  4. New sqllogictest cases in subquery_projection.slt:

    • an EXPLAIN guard that shows one hash mark join for each subquery,
    • an EXPLAIN guard that shows the three join fallback when a residual filter remains,
    • NULL semantics cases: IN and NOT IN with a NULL in the subquery, a NULL outer value, NOT inside CASE, a projection over an aggregate, the COALESCE and cast shape, and results for the residual filter shape.

    All of these were checked against DuckDB and PostgreSQL.

  5. join_keys_may_be_null now decides null-awareness from the equijoin key expressions, not from the columns they reference. A key such as NULLIF(id, 1) or TRY_CAST(s AS INT) can be NULL over a NOT NULL column. Before this change such a key gave a plain mark join, so the projected IN returned false instead of NULL. The same helper feeds the LeftAnti path, so WHERE NULLIF(id, 1) NOT IN (SELECT ...) on main kept a row that it must drop. Both paths now plan a null-aware join for these keys.

    The expression test applies only when the split gives keys and no residual filter. A residual keeps the older column test, as more than one key already does. The reason is the LeftAnti executor: it does not apply the residual when it decides whether a NULL makes the result UNKNOWN (Wrong results: correlated NOT IN with a non-equality correlation returns no rows (null-aware LeftAnti join ignores the residual filter) #25336), so it would drop a build row whose correlated subquery result is empty, and NULL NOT IN (<empty set>) is TRUE. subquery_projection.slt pins both directions of that shape. Every result of this branch is thus the same as main's or better.

DuckDB comparison

For an absolute reference, the same seven queries in datafusion-cli and in DuckDB 1.5.2, on the same two tables, release build, Apple M4 Pro. main is the merge-base 64871d9 and "this PR" is 3af87370c1. The tables are the ones the suite builds, at its default of 30,000 rows each. Each number is the median of 7 runs. One round runs one session per engine, and the rounds interleave the three engines.

Query main this PR DuckDB
q01 bare IN 533 ms 2 ms 2 ms
q02 COALESCE over IN 1352 ms 3 ms 2 ms
q03 correlated IN, equality 14 ms 3 ms 3 ms
q04 two IN columns 1026 ms 3 ms 2 ms
q05 bare NOT IN 646 ms 1 ms 2 ms
q06 correlated EXISTS 4 ms 2 ms 2 ms
q07 correlated IN, non-equality 117 ms 93 ms 458 ms

All three engines give the same result for all seven queries, and the counts are the ones in the suite's checked-in result files.

For the four quadratic shapes, q01, q02, q04 and q05, main is 270x to 680x slower than DuckDB. This PR puts them at DuckDB's cost. These times are at the 1 ms resolution of both command line tools, so the exact factor is approximate; the size of the difference is not.

q07 keeps the three-join plan, which this PR does not change. DataFusion is 4.9x faster than DuckDB there, before and after.

A second run at 100,000 rows per table gives the same picture: main takes 2741 ms to 6355 ms for q01, q02, q04 and q05, this PR takes 2 ms to 4 ms and DuckDB 3 ms to 4 ms, and q07 takes 971 ms against DuckDB's 1534 ms. All three engines again give the same counts.

How to run it

The queries are the suite's own benchmarks/sql_benchmarks/projection_subquery/queries/q0*.sql, with an alias added to the derived table. The load SQL needs one change for DuckDB, because generate_series gives a column of that name there and a column named value in DataFusion:

CREATE TABLE outer_t AS
SELECT
  CAST(value AS INT) AS id,
  CAST(value % 1000 AS INT) AS z
FROM generate_series(1, 30000) AS g(value);

CREATE TABLE inner_t AS
SELECT
  CASE WHEN value % 97 = 0 THEN NULL ELSE CAST(value * 2 AS INT) END AS id,
  CAST(value % 1000 AS INT) AS z
FROM generate_series(1, 30000) AS g(value);

datafusion-cli reports the time of each statement as Elapsed, and duckdb reports it as Run Time (s): real after .timer on.

What is the testing strategy for this PR?

  • Unit tests in datafusion/optimizer/src/decorrelate_predicate_subquery.rs. The updated snapshots now show a single mark join. There are new tests for the residual filter fallback and for NOT IN.
  • The new sqllogictest cases in subquery_projection.slt listed above, checked against DuckDB and PostgreSQL.
  • The existing subquery_projection.slt cases pass without any change.
  • New unit tests and a new subquery_projection.slt section cover nullable key expressions over non-nullable columns: a NULLIF left key, a TRY_CAST left key, a NULLIF right key, NOT IN, and the WHERE form. The expected values agree with DuckDB and PostgreSQL.
  • The full sqllogictest suite and the optimizer crate are green locally.
  • The benchmark numbers above.

Are there any user-facing changes?

There are no changes to query results and no changes to any public API. Plans for projected IN and NOT IN subqueries are much faster. No documentation change is needed.

🤖 Generated with Claude Code

@github-actions github-actions Bot added optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt) labels Sep 15, 2026
@adriangb
adriangb force-pushed the in-exists-subquery-projection branch from 9e94b59 to 04f3d7d Compare September 15, 2026 19:17
@adriangb adriangb changed the title feat: support InSubquery and Exists in Projection expressions perf: use one null-aware mark join for hashable IN subqueries in projections Sep 15, 2026
@codecov-commenter

codecov-commenter commented Sep 15, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.55438% with 62 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.41%. Comparing base (64871d9) to head (1a9d842).
⚠️ Report is 35 commits behind head on main.

Files with missing lines Patch % Lines
...on/optimizer/src/decorrelate_predicate_subquery.rs 83.60% 17 Missing and 44 partials ⚠️
datafusion/optimizer/src/decorrelate.rs 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #25338      +/-   ##
==========================================
+ Coverage   82.36%   82.41%   +0.04%     
==========================================
  Files        1137     1138       +1     
  Lines      432937   435575    +2638     
  Branches   432937   435575    +2638     
==========================================
+ Hits       356589   358977    +2388     
- Misses      54821    54858      +37     
- Partials    21527    21740     +213     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@adriangb

Copy link
Copy Markdown
Contributor Author

@kosiew since you reviewed #24972 would you mind taking a look here? cc @neilconway since you were involved in #21363

@adriangb

Copy link
Copy Markdown
Contributor Author

run benchmarks

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5687257997-2377-hfl77 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5687257997-2378-jf2f2 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark tpcds

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5687257997-2379-szrcx 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark tpch

Results will be posted here when complete


File an issue against this benchmark runner

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Expression-level nullability can be missed, causing projected IN to return false instead of UNKNOWN.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Optimizes projected IN/NOT IN subqueries by using a single null-aware mark join when possible.

Changes:

  • Tracks whether mark joins preserve three-valued logic.
  • Retains three-join fallback for residual predicates.
  • Adds plan and NULL-semantics regression tests.
File summaries
File Description
datafusion/optimizer/src/decorrelate_predicate_subquery.rs Implements single-mark-join optimization.
datafusion/sqllogictest/test_files/subquery_projection.slt Tests plans and NULL semantics.
datafusion/sqllogictest/test_files/projection_pushdown.slt Updates alias-collision regression coverage.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread datafusion/optimizer/src/decorrelate_predicate_subquery.rs Outdated
@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark tpch
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query     ┃     HEAD ┃ in-exists-subquery-projection ┃    Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 1  │ 38.63 ms │                      38.67 ms │ no change │
│ QQuery 2  │ 18.88 ms │                      18.89 ms │ no change │
│ QQuery 3  │ 29.09 ms │                      28.70 ms │ no change │
│ QQuery 4  │ 17.61 ms │                      17.66 ms │ no change │
│ QQuery 5  │ 35.97 ms │                      35.89 ms │ no change │
│ QQuery 6  │ 16.11 ms │                      16.08 ms │ no change │
│ QQuery 7  │ 41.79 ms │                      42.43 ms │ no change │
│ QQuery 8  │ 41.38 ms │                      41.02 ms │ no change │
│ QQuery 9  │ 49.43 ms │                      50.09 ms │ no change │
│ QQuery 10 │ 42.28 ms │                      42.51 ms │ no change │
│ QQuery 11 │ 13.59 ms │                      13.64 ms │ no change │
│ QQuery 12 │ 24.12 ms │                      23.91 ms │ no change │
│ QQuery 13 │ 39.91 ms │                      39.40 ms │ no change │
│ QQuery 14 │ 24.47 ms │                      24.49 ms │ no change │
│ QQuery 15 │ 30.82 ms │                      30.91 ms │ no change │
│ QQuery 16 │ 13.81 ms │                      13.74 ms │ no change │
│ QQuery 17 │ 71.46 ms │                      71.66 ms │ no change │
│ QQuery 18 │ 61.89 ms │                      61.37 ms │ no change │
│ QQuery 19 │ 33.16 ms │                      32.94 ms │ no change │
│ QQuery 20 │ 31.88 ms │                      31.82 ms │ no change │
│ QQuery 21 │ 56.05 ms │                      56.27 ms │ no change │
│ QQuery 22 │ 14.02 ms │                      14.35 ms │ no change │
└───────────┴──────────┴───────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Benchmark Summary                            ┃          ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 746.36ms │
│ Total Time (in-exists-subquery-projection)   │ 746.43ms │
│ Average Time (HEAD)                          │  33.93ms │
│ Average Time (in-exists-subquery-projection) │  33.93ms │
│ Queries Faster                               │        0 │
│ Queries Slower                               │        0 │
│ Queries with No Change                       │       22 │
│ Queries with Failure                         │        0 │
└──────────────────────────────────────────────┴──────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query     ┃                           HEAD ┃  in-exists-subquery-projection ┃    Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 1  │ 38.63 / 39.52 ±1.16 / 41.67 ms │ 38.67 / 39.77 ±1.30 / 41.53 ms │ no change │
│ QQuery 2  │ 18.88 / 19.34 ±0.37 / 19.82 ms │ 18.89 / 19.20 ±0.25 / 19.54 ms │ no change │
│ QQuery 3  │ 29.09 / 29.24 ±0.15 / 29.53 ms │ 28.70 / 29.08 ±0.39 / 29.83 ms │ no change │
│ QQuery 4  │ 17.61 / 18.03 ±0.53 / 19.08 ms │ 17.66 / 18.11 ±0.50 / 19.05 ms │ no change │
│ QQuery 5  │ 35.97 / 36.48 ±0.37 / 37.10 ms │ 35.89 / 36.88 ±0.89 / 38.48 ms │ no change │
│ QQuery 6  │ 16.11 / 16.79 ±1.02 / 18.81 ms │ 16.08 / 17.25 ±0.85 / 18.41 ms │ no change │
│ QQuery 7  │ 41.79 / 42.52 ±0.42 / 42.99 ms │ 42.43 / 43.26 ±0.90 / 44.86 ms │ no change │
│ QQuery 8  │ 41.38 / 43.00 ±1.54 / 45.66 ms │ 41.02 / 41.31 ±0.24 / 41.66 ms │ no change │
│ QQuery 9  │ 49.43 / 50.56 ±1.33 / 52.85 ms │ 50.09 / 51.17 ±1.05 / 53.08 ms │ no change │
│ QQuery 10 │ 42.28 / 42.49 ±0.17 / 42.68 ms │ 42.51 / 43.24 ±0.57 / 43.98 ms │ no change │
│ QQuery 11 │ 13.59 / 13.81 ±0.16 / 14.02 ms │ 13.64 / 13.85 ±0.14 / 14.03 ms │ no change │
│ QQuery 12 │ 24.12 / 24.37 ±0.13 / 24.50 ms │ 23.91 / 24.41 ±0.37 / 24.93 ms │ no change │
│ QQuery 13 │ 39.91 / 41.31 ±1.53 / 43.35 ms │ 39.40 / 40.70 ±1.00 / 41.86 ms │ no change │
│ QQuery 14 │ 24.47 / 25.13 ±0.96 / 27.01 ms │ 24.49 / 24.67 ±0.15 / 24.93 ms │ no change │
│ QQuery 15 │ 30.82 / 31.39 ±0.59 / 32.26 ms │ 30.91 / 31.13 ±0.27 / 31.62 ms │ no change │
│ QQuery 16 │ 13.81 / 13.95 ±0.13 / 14.14 ms │ 13.74 / 13.97 ±0.12 / 14.06 ms │ no change │
│ QQuery 17 │ 71.46 / 74.32 ±1.63 / 76.08 ms │ 71.66 / 73.25 ±1.21 / 75.02 ms │ no change │
│ QQuery 18 │ 61.89 / 62.58 ±0.41 / 63.17 ms │ 61.37 / 62.17 ±0.73 / 63.50 ms │ no change │
│ QQuery 19 │ 33.16 / 33.49 ±0.22 / 33.81 ms │ 32.94 / 33.69 ±0.74 / 35.10 ms │ no change │
│ QQuery 20 │ 31.88 / 32.55 ±0.64 / 33.64 ms │ 31.82 / 32.57 ±0.59 / 33.33 ms │ no change │
│ QQuery 21 │ 56.05 / 57.28 ±1.38 / 59.30 ms │ 56.27 / 57.90 ±1.34 / 60.13 ms │ no change │
│ QQuery 22 │ 14.02 / 14.14 ±0.12 / 14.36 ms │ 14.35 / 14.60 ±0.21 / 14.98 ms │ no change │
└───────────┴────────────────────────────────┴────────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Benchmark Summary                            ┃          ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 762.27ms │
│ Total Time (in-exists-subquery-projection)   │ 762.16ms │
│ Average Time (HEAD)                          │  34.65ms │
│ Average Time (in-exists-subquery-projection) │  34.64ms │
│ Queries Faster                               │        0 │
│ Queries Slower                               │        0 │
│ Queries with No Change                       │       22 │
│ Queries with Failure                         │        0 │
└──────────────────────────────────────────────┴──────────┘

Resource Usage

tpch — base (merge-base)

Metric Value
Wall time 5.0s
Peak memory 1.2 GiB
Avg memory 479.8 MiB
CPU user 21.3s
CPU sys 1.8s
Peak spill 0 B

tpch — branch

Metric Value
Wall time 5.0s
Peak memory 1.2 GiB
Avg memory 502.6 MiB
CPU user 21.5s
CPU sys 1.7s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark tpcds
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1  │    5.60 ms │                       5.65 ms │     no change │
│ QQuery 2  │   80.59 ms │                      81.35 ms │     no change │
│ QQuery 3  │   28.90 ms │                      29.26 ms │     no change │
│ QQuery 4  │  487.96 ms │                     478.89 ms │     no change │
│ QQuery 5  │   51.85 ms │                      52.23 ms │     no change │
│ QQuery 6  │   35.91 ms │                      36.32 ms │     no change │
│ QQuery 7  │   74.41 ms │                      74.97 ms │     no change │
│ QQuery 8  │   36.57 ms │                      36.57 ms │     no change │
│ QQuery 9  │   52.90 ms │                      50.12 ms │ +1.06x faster │
│ QQuery 10 │   61.39 ms │                      62.18 ms │     no change │
│ QQuery 11 │  294.53 ms │                     294.07 ms │     no change │
│ QQuery 12 │   28.45 ms │                      28.62 ms │     no change │
│ QQuery 13 │  118.07 ms │                     117.72 ms │     no change │
│ QQuery 14 │  417.71 ms │                     419.36 ms │     no change │
│ QQuery 15 │   56.68 ms │                      56.43 ms │     no change │
│ QQuery 16 │    6.49 ms │                       6.75 ms │     no change │
│ QQuery 17 │   80.44 ms │                      80.63 ms │     no change │
│ QQuery 18 │  104.14 ms │                     104.49 ms │     no change │
│ QQuery 19 │   41.05 ms │                      41.38 ms │     no change │
│ QQuery 20 │   35.48 ms │                      35.63 ms │     no change │
│ QQuery 21 │   17.37 ms │                      17.41 ms │     no change │
│ QQuery 22 │   62.65 ms │                      62.65 ms │     no change │
│ QQuery 23 │  311.45 ms │                     313.55 ms │     no change │
│ QQuery 24 │  193.56 ms │                     195.97 ms │     no change │
│ QQuery 25 │  111.06 ms │                     110.98 ms │     no change │
│ QQuery 26 │   47.98 ms │                      48.59 ms │     no change │
│ QQuery 27 │    6.17 ms │                       6.04 ms │     no change │
│ QQuery 28 │   60.84 ms │                      55.74 ms │ +1.09x faster │
│ QQuery 29 │   96.72 ms │                      98.50 ms │     no change │
│ QQuery 30 │   32.34 ms │                      32.48 ms │     no change │
│ QQuery 31 │  109.82 ms │                     110.34 ms │     no change │
│ QQuery 32 │   19.87 ms │                      20.13 ms │     no change │
│ QQuery 33 │   37.80 ms │                      37.68 ms │     no change │
│ QQuery 34 │    9.98 ms │                       9.78 ms │     no change │
│ QQuery 35 │   71.39 ms │                      71.49 ms │     no change │
│ QQuery 36 │    5.76 ms │                       5.79 ms │     no change │
│ QQuery 37 │    6.80 ms │                       6.82 ms │     no change │
│ QQuery 38 │   61.31 ms │                      62.27 ms │     no change │
│ QQuery 39 │   89.18 ms │                      88.89 ms │     no change │
│ QQuery 40 │   23.34 ms │                      23.42 ms │     no change │
│ QQuery 41 │   11.06 ms │                      11.15 ms │     no change │
│ QQuery 42 │   23.47 ms │                      23.93 ms │     no change │
│ QQuery 43 │    5.00 ms │                       5.17 ms │     no change │
│ QQuery 44 │    9.21 ms │                       9.38 ms │     no change │
│ QQuery 45 │   38.37 ms │                      38.71 ms │     no change │
│ QQuery 46 │   11.83 ms │                      12.07 ms │     no change │
│ QQuery 47 │  229.49 ms │                     227.91 ms │     no change │
│ QQuery 48 │   95.49 ms │                      95.66 ms │     no change │
│ QQuery 49 │   71.02 ms │                      70.97 ms │     no change │
│ QQuery 50 │   59.20 ms │                      59.06 ms │     no change │
│ QQuery 51 │   90.14 ms │                      90.72 ms │     no change │
│ QQuery 52 │   24.36 ms │                      23.78 ms │     no change │
│ QQuery 53 │   29.03 ms │                      28.95 ms │     no change │
│ QQuery 54 │   54.51 ms │                      53.91 ms │     no change │
│ QQuery 55 │   23.29 ms │                      23.24 ms │     no change │
│ QQuery 56 │   39.13 ms │                      38.56 ms │     no change │
│ QQuery 57 │  175.70 ms │                     175.83 ms │     no change │
│ QQuery 58 │  112.64 ms │                     112.07 ms │     no change │
│ QQuery 59 │  117.56 ms │                     117.71 ms │     no change │
│ QQuery 60 │   39.96 ms │                      38.77 ms │     no change │
│ QQuery 61 │   12.07 ms │                      12.07 ms │     no change │
│ QQuery 62 │   46.26 ms │                      46.11 ms │     no change │
│ QQuery 63 │   29.16 ms │                      29.36 ms │     no change │
│ QQuery 64 │  367.34 ms │                     369.03 ms │     no change │
│ QQuery 65 │  123.86 ms │                     123.68 ms │     no change │
│ QQuery 66 │   79.04 ms │                      78.56 ms │     no change │
│ QQuery 67 │  243.99 ms │                     238.00 ms │     no change │
│ QQuery 68 │   11.88 ms │                      11.84 ms │     no change │
│ QQuery 69 │   55.58 ms │                      56.02 ms │     no change │
│ QQuery 70 │  104.47 ms │                     104.34 ms │     no change │
│ QQuery 71 │   35.03 ms │                      35.19 ms │     no change │
│ QQuery 72 │ 1822.26 ms │                    1777.64 ms │     no change │
│ QQuery 73 │   10.17 ms │                       9.71 ms │     no change │
│ QQuery 74 │  170.78 ms │                     168.81 ms │     no change │
│ QQuery 75 │  146.05 ms │                     146.55 ms │     no change │
│ QQuery 76 │   34.72 ms │                      35.14 ms │     no change │
│ QQuery 77 │   61.54 ms │                      61.06 ms │     no change │
│ QQuery 78 │  220.73 ms │                     222.09 ms │     no change │
│ QQuery 79 │   66.84 ms │                      66.69 ms │     no change │
│ QQuery 80 │   98.23 ms │                      98.75 ms │     no change │
│ QQuery 81 │   25.74 ms │                      25.78 ms │     no change │
│ QQuery 82 │   16.12 ms │                      16.12 ms │     no change │
│ QQuery 83 │   33.86 ms │                      34.05 ms │     no change │
│ QQuery 84 │   29.25 ms │                      29.34 ms │     no change │
│ QQuery 85 │  103.62 ms │                     102.10 ms │     no change │
│ QQuery 86 │   24.73 ms │                      24.96 ms │     no change │
│ QQuery 87 │   61.25 ms │                      61.30 ms │     no change │
│ QQuery 88 │   63.01 ms │                      63.01 ms │     no change │
│ QQuery 89 │   35.78 ms │                      35.44 ms │     no change │
│ QQuery 90 │   16.72 ms │                      16.78 ms │     no change │
│ QQuery 91 │   44.40 ms │                      45.11 ms │     no change │
│ QQuery 92 │   28.51 ms │                      28.62 ms │     no change │
│ QQuery 93 │   49.61 ms │                      49.59 ms │     no change │
│ QQuery 94 │   37.29 ms │                      37.34 ms │     no change │
│ QQuery 95 │   79.36 ms │                      80.77 ms │     no change │
│ QQuery 96 │   23.56 ms │                      23.77 ms │     no change │
│ QQuery 97 │   50.68 ms │                      51.16 ms │     no change │
│ QQuery 98 │   42.82 ms │                      42.27 ms │     no change │
│ QQuery 99 │   70.10 ms │                      70.21 ms │     no change │
└───────────┴────────────┴───────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 9311.40ms │
│ Total Time (in-exists-subquery-projection)   │ 9257.05ms │
│ Average Time (HEAD)                          │   94.05ms │
│ Average Time (in-exists-subquery-projection) │   93.51ms │
│ Queries Faster                               │         2 │
│ Queries Slower                               │         0 │
│ Queries with No Change                       │        97 │
│ Queries with Failure                         │         0 │
└──────────────────────────────────────────────┴───────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃         in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1  │           5.60 / 6.16 ±0.94 / 8.03 ms │           5.65 / 6.18 ±0.91 / 7.99 ms │     no change │
│ QQuery 2  │        80.59 / 80.93 ±0.23 / 81.18 ms │        81.35 / 81.73 ±0.25 / 82.02 ms │     no change │
│ QQuery 3  │        28.90 / 29.35 ±0.33 / 29.80 ms │        29.26 / 29.34 ±0.06 / 29.43 ms │     no change │
│ QQuery 4  │     487.96 / 496.44 ±5.70 / 505.73 ms │    478.89 / 502.16 ±29.50 / 560.43 ms │     no change │
│ QQuery 5  │        51.85 / 52.25 ±0.40 / 52.85 ms │        52.23 / 52.50 ±0.40 / 53.30 ms │     no change │
│ QQuery 6  │        35.91 / 36.43 ±0.48 / 37.22 ms │        36.32 / 36.52 ±0.22 / 36.95 ms │     no change │
│ QQuery 7  │        74.41 / 74.75 ±0.27 / 75.06 ms │        74.97 / 75.34 ±0.39 / 75.95 ms │     no change │
│ QQuery 8  │        36.57 / 37.64 ±1.90 / 41.44 ms │        36.57 / 37.00 ±0.42 / 37.76 ms │     no change │
│ QQuery 9  │        52.90 / 54.38 ±1.50 / 56.45 ms │        50.12 / 53.16 ±1.82 / 55.86 ms │     no change │
│ QQuery 10 │        61.39 / 61.75 ±0.23 / 62.04 ms │        62.18 / 62.51 ±0.26 / 62.93 ms │     no change │
│ QQuery 11 │     294.53 / 301.47 ±4.35 / 307.29 ms │     294.07 / 298.31 ±2.82 / 302.62 ms │     no change │
│ QQuery 12 │        28.45 / 28.88 ±0.30 / 29.17 ms │        28.62 / 29.09 ±0.37 / 29.54 ms │     no change │
│ QQuery 13 │     118.07 / 118.83 ±0.43 / 119.26 ms │     117.72 / 118.29 ±0.42 / 118.86 ms │     no change │
│ QQuery 14 │     417.71 / 419.98 ±2.38 / 424.01 ms │     419.36 / 423.04 ±1.92 / 424.71 ms │     no change │
│ QQuery 15 │        56.68 / 57.25 ±0.46 / 58.07 ms │        56.43 / 57.25 ±0.86 / 58.58 ms │     no change │
│ QQuery 16 │           6.49 / 6.69 ±0.25 / 7.18 ms │           6.75 / 6.88 ±0.19 / 7.26 ms │     no change │
│ QQuery 17 │        80.44 / 82.48 ±1.96 / 85.25 ms │        80.63 / 82.40 ±2.19 / 86.71 ms │     no change │
│ QQuery 18 │     104.14 / 105.33 ±0.87 / 106.77 ms │     104.49 / 105.68 ±0.89 / 107.05 ms │     no change │
│ QQuery 19 │        41.05 / 41.44 ±0.31 / 41.85 ms │        41.38 / 41.88 ±0.66 / 43.15 ms │     no change │
│ QQuery 20 │        35.48 / 36.25 ±0.47 / 36.93 ms │        35.63 / 36.12 ±0.27 / 36.41 ms │     no change │
│ QQuery 21 │        17.37 / 17.62 ±0.29 / 18.14 ms │        17.41 / 18.16 ±0.80 / 19.43 ms │     no change │
│ QQuery 22 │        62.65 / 63.70 ±0.61 / 64.49 ms │        62.65 / 64.16 ±1.48 / 66.81 ms │     no change │
│ QQuery 23 │     311.45 / 313.16 ±1.07 / 314.32 ms │     313.55 / 316.48 ±2.56 / 321.14 ms │     no change │
│ QQuery 24 │     193.56 / 197.05 ±3.40 / 203.40 ms │     195.97 / 200.42 ±4.43 / 208.12 ms │     no change │
│ QQuery 25 │     111.06 / 111.40 ±0.31 / 111.83 ms │     110.98 / 114.24 ±2.96 / 118.79 ms │     no change │
│ QQuery 26 │        47.98 / 48.72 ±0.40 / 49.09 ms │        48.59 / 49.01 ±0.22 / 49.22 ms │     no change │
│ QQuery 27 │           6.17 / 6.35 ±0.22 / 6.77 ms │           6.04 / 6.34 ±0.31 / 6.94 ms │     no change │
│ QQuery 28 │        60.84 / 62.11 ±1.90 / 65.87 ms │        55.74 / 61.02 ±4.23 / 68.69 ms │     no change │
│ QQuery 29 │        96.72 / 98.38 ±0.99 / 99.76 ms │      98.50 / 100.69 ±1.48 / 102.68 ms │     no change │
│ QQuery 30 │        32.34 / 32.47 ±0.12 / 32.66 ms │        32.48 / 32.76 ±0.16 / 32.93 ms │     no change │
│ QQuery 31 │     109.82 / 112.21 ±2.49 / 116.93 ms │     110.34 / 112.85 ±2.42 / 117.05 ms │     no change │
│ QQuery 32 │        19.87 / 20.89 ±1.15 / 23.11 ms │        20.13 / 20.37 ±0.25 / 20.81 ms │     no change │
│ QQuery 33 │        37.80 / 38.04 ±0.13 / 38.17 ms │        37.68 / 38.03 ±0.28 / 38.46 ms │     no change │
│ QQuery 34 │         9.98 / 10.16 ±0.17 / 10.39 ms │         9.78 / 10.06 ±0.22 / 10.38 ms │     no change │
│ QQuery 35 │        71.39 / 71.98 ±0.53 / 72.66 ms │        71.49 / 71.97 ±0.34 / 72.53 ms │     no change │
│ QQuery 36 │          5.76 / 6.64 ±1.71 / 10.06 ms │           5.79 / 5.93 ±0.16 / 6.24 ms │ +1.12x faster │
│ QQuery 37 │           6.80 / 6.92 ±0.11 / 7.12 ms │          6.82 / 7.78 ±1.73 / 11.23 ms │  1.12x slower │
│ QQuery 38 │        61.31 / 62.30 ±0.95 / 63.95 ms │        62.27 / 62.71 ±0.26 / 63.01 ms │     no change │
│ QQuery 39 │        89.18 / 89.90 ±0.54 / 90.66 ms │        88.89 / 89.44 ±0.66 / 90.73 ms │     no change │
│ QQuery 40 │        23.34 / 23.77 ±0.31 / 24.18 ms │        23.42 / 23.87 ±0.33 / 24.44 ms │     no change │
│ QQuery 41 │        11.06 / 11.18 ±0.18 / 11.53 ms │        11.15 / 11.33 ±0.13 / 11.49 ms │     no change │
│ QQuery 42 │        23.47 / 24.23 ±0.90 / 25.97 ms │        23.93 / 24.48 ±0.38 / 25.10 ms │     no change │
│ QQuery 43 │           5.00 / 5.14 ±0.18 / 5.51 ms │           5.17 / 5.27 ±0.14 / 5.55 ms │     no change │
│ QQuery 44 │           9.21 / 9.30 ±0.08 / 9.45 ms │           9.38 / 9.51 ±0.09 / 9.64 ms │     no change │
│ QQuery 45 │        38.37 / 39.46 ±1.60 / 42.63 ms │        38.71 / 40.02 ±1.17 / 41.86 ms │     no change │
│ QQuery 46 │        11.83 / 12.09 ±0.22 / 12.40 ms │        12.07 / 12.39 ±0.25 / 12.74 ms │     no change │
│ QQuery 47 │     229.49 / 229.84 ±0.39 / 230.59 ms │     227.91 / 231.32 ±3.68 / 236.85 ms │     no change │
│ QQuery 48 │        95.49 / 96.22 ±1.12 / 98.46 ms │        95.66 / 96.09 ±0.30 / 96.52 ms │     no change │
│ QQuery 49 │        71.02 / 72.42 ±2.22 / 76.83 ms │        70.97 / 71.43 ±0.51 / 72.33 ms │     no change │
│ QQuery 50 │        59.20 / 59.93 ±0.45 / 60.52 ms │        59.06 / 59.43 ±0.44 / 60.28 ms │     no change │
│ QQuery 51 │        90.14 / 93.55 ±2.19 / 96.44 ms │        90.72 / 93.26 ±2.37 / 97.03 ms │     no change │
│ QQuery 52 │        24.36 / 24.51 ±0.13 / 24.74 ms │        23.78 / 24.36 ±0.49 / 25.28 ms │     no change │
│ QQuery 53 │        29.03 / 29.74 ±1.00 / 31.74 ms │        28.95 / 29.19 ±0.19 / 29.54 ms │     no change │
│ QQuery 54 │        54.51 / 54.73 ±0.14 / 54.89 ms │        53.91 / 54.74 ±0.82 / 56.30 ms │     no change │
│ QQuery 55 │        23.29 / 23.84 ±0.44 / 24.47 ms │        23.24 / 23.48 ±0.15 / 23.71 ms │     no change │
│ QQuery 56 │        39.13 / 40.53 ±2.61 / 45.74 ms │        38.56 / 39.15 ±0.37 / 39.64 ms │     no change │
│ QQuery 57 │     175.70 / 176.94 ±0.77 / 177.83 ms │     175.83 / 178.58 ±4.36 / 187.26 ms │     no change │
│ QQuery 58 │     112.64 / 114.34 ±2.16 / 118.54 ms │     112.07 / 114.55 ±2.93 / 120.15 ms │     no change │
│ QQuery 59 │     117.56 / 118.76 ±1.20 / 120.90 ms │     117.71 / 119.23 ±2.49 / 124.19 ms │     no change │
│ QQuery 60 │        39.96 / 40.21 ±0.20 / 40.48 ms │        38.77 / 40.32 ±0.86 / 41.37 ms │     no change │
│ QQuery 61 │        12.07 / 12.24 ±0.22 / 12.68 ms │        12.07 / 12.33 ±0.24 / 12.78 ms │     no change │
│ QQuery 62 │        46.26 / 47.40 ±0.81 / 48.62 ms │        46.11 / 46.46 ±0.30 / 46.86 ms │     no change │
│ QQuery 63 │        29.16 / 29.73 ±0.34 / 30.20 ms │        29.36 / 29.60 ±0.29 / 30.14 ms │     no change │
│ QQuery 64 │     367.34 / 369.85 ±1.93 / 372.82 ms │     369.03 / 372.54 ±3.36 / 378.10 ms │     no change │
│ QQuery 65 │     123.86 / 127.59 ±3.45 / 133.86 ms │     123.68 / 127.02 ±3.06 / 132.52 ms │     no change │
│ QQuery 66 │        79.04 / 80.44 ±0.99 / 81.61 ms │        78.56 / 79.56 ±0.75 / 80.79 ms │     no change │
│ QQuery 67 │     243.99 / 246.65 ±2.21 / 249.38 ms │     238.00 / 244.23 ±3.54 / 248.33 ms │     no change │
│ QQuery 68 │        11.88 / 12.09 ±0.17 / 12.37 ms │        11.84 / 12.01 ±0.21 / 12.43 ms │     no change │
│ QQuery 69 │        55.58 / 57.93 ±3.22 / 64.33 ms │        56.02 / 58.98 ±4.83 / 68.58 ms │     no change │
│ QQuery 70 │     104.47 / 106.04 ±1.75 / 109.44 ms │     104.34 / 105.75 ±1.69 / 108.94 ms │     no change │
│ QQuery 71 │        35.03 / 35.98 ±0.84 / 37.55 ms │        35.19 / 35.49 ±0.29 / 35.97 ms │     no change │
│ QQuery 72 │ 1822.26 / 1889.88 ±46.85 / 1965.09 ms │ 1777.64 / 1857.20 ±66.62 / 1958.83 ms │     no change │
│ QQuery 73 │        10.17 / 11.29 ±1.23 / 13.67 ms │         9.71 / 10.24 ±0.59 / 11.34 ms │ +1.10x faster │
│ QQuery 74 │     170.78 / 173.90 ±1.96 / 176.02 ms │     168.81 / 171.31 ±2.04 / 174.88 ms │     no change │
│ QQuery 75 │     146.05 / 147.30 ±0.79 / 148.33 ms │     146.55 / 147.64 ±1.04 / 148.95 ms │     no change │
│ QQuery 76 │        34.72 / 37.13 ±4.19 / 45.50 ms │        35.14 / 35.49 ±0.24 / 35.83 ms │     no change │
│ QQuery 77 │        61.54 / 62.66 ±1.74 / 66.12 ms │        61.06 / 64.43 ±3.93 / 71.92 ms │     no change │
│ QQuery 78 │     220.73 / 224.58 ±4.49 / 233.34 ms │     222.09 / 226.55 ±4.05 / 232.90 ms │     no change │
│ QQuery 79 │        66.84 / 67.59 ±1.24 / 70.05 ms │        66.69 / 66.93 ±0.26 / 67.43 ms │     no change │
│ QQuery 80 │       98.23 / 99.75 ±0.85 / 100.60 ms │      98.75 / 101.43 ±3.38 / 107.61 ms │     no change │
│ QQuery 81 │        25.74 / 26.01 ±0.15 / 26.19 ms │        25.78 / 26.74 ±1.48 / 29.67 ms │     no change │
│ QQuery 82 │        16.12 / 16.30 ±0.13 / 16.48 ms │        16.12 / 16.66 ±0.62 / 17.79 ms │     no change │
│ QQuery 83 │        33.86 / 34.38 ±0.29 / 34.74 ms │        34.05 / 34.23 ±0.22 / 34.60 ms │     no change │
│ QQuery 84 │        29.25 / 29.51 ±0.18 / 29.68 ms │        29.34 / 29.54 ±0.13 / 29.69 ms │     no change │
│ QQuery 85 │     103.62 / 107.00 ±3.48 / 113.45 ms │     102.10 / 106.56 ±6.19 / 118.60 ms │     no change │
│ QQuery 86 │        24.73 / 25.36 ±0.35 / 25.64 ms │        24.96 / 25.32 ±0.23 / 25.67 ms │     no change │
│ QQuery 87 │        61.25 / 62.04 ±0.42 / 62.48 ms │        61.30 / 62.29 ±0.61 / 63.21 ms │     no change │
│ QQuery 88 │        63.01 / 65.74 ±5.13 / 75.99 ms │        63.01 / 63.47 ±0.35 / 63.80 ms │     no change │
│ QQuery 89 │        35.78 / 36.76 ±1.14 / 38.89 ms │        35.44 / 37.45 ±2.92 / 43.21 ms │     no change │
│ QQuery 90 │        16.72 / 17.01 ±0.17 / 17.23 ms │        16.78 / 17.39 ±0.97 / 19.32 ms │     no change │
│ QQuery 91 │        44.40 / 44.65 ±0.22 / 44.95 ms │        45.11 / 45.49 ±0.38 / 46.22 ms │     no change │
│ QQuery 92 │        28.51 / 29.06 ±0.57 / 29.94 ms │        28.62 / 29.18 ±0.32 / 29.50 ms │     no change │
│ QQuery 93 │        49.61 / 50.91 ±1.13 / 52.59 ms │        49.59 / 50.24 ±0.66 / 51.31 ms │     no change │
│ QQuery 94 │        37.29 / 37.81 ±0.56 / 38.62 ms │        37.34 / 38.63 ±1.88 / 42.35 ms │     no change │
│ QQuery 95 │        79.36 / 81.62 ±2.26 / 85.74 ms │        80.77 / 81.47 ±0.59 / 82.29 ms │     no change │
│ QQuery 96 │        23.56 / 23.89 ±0.25 / 24.32 ms │        23.77 / 24.03 ±0.29 / 24.59 ms │     no change │
│ QQuery 97 │        50.68 / 52.93 ±2.62 / 57.77 ms │        51.16 / 51.52 ±0.53 / 52.57 ms │     no change │
│ QQuery 98 │        42.82 / 43.53 ±0.54 / 44.06 ms │        42.27 / 45.53 ±5.68 / 56.87 ms │     no change │
│ QQuery 99 │        70.10 / 71.05 ±0.64 / 71.87 ms │        70.21 / 71.15 ±0.67 / 72.23 ms │     no change │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 9495.00ms │
│ Total Time (in-exists-subquery-projection)   │ 9481.85ms │
│ Average Time (HEAD)                          │   95.91ms │
│ Average Time (in-exists-subquery-projection) │   95.78ms │
│ Queries Faster                               │         2 │
│ Queries Slower                               │         1 │
│ Queries with No Change                       │        96 │
│ Queries with Failure                         │         0 │
└──────────────────────────────────────────────┴───────────┘

Resource Usage

tpcds — base (merge-base)

Metric Value
Wall time 50.0s
Peak memory 2.1 GiB
Avg memory 1.4 GiB
CPU user 205.7s
CPU sys 5.6s
Peak spill 0 B

tpcds — branch

Metric Value
Wall time 50.0s
Peak memory 1.9 GiB
Avg memory 1.3 GiB
CPU user 204.4s
CPU sys 5.5s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │    1.20 ms │                       1.31 ms │  1.09x slower │
│ QQuery 1  │   11.64 ms │                      11.99 ms │     no change │
│ QQuery 2  │   36.24 ms │                      37.10 ms │     no change │
│ QQuery 3  │   33.09 ms │                      32.32 ms │     no change │
│ QQuery 4  │  235.57 ms │                     223.59 ms │ +1.05x faster │
│ QQuery 5  │  307.17 ms │                     274.83 ms │ +1.12x faster │
│ QQuery 6  │    1.41 ms │                       1.26 ms │ +1.12x faster │
│ QQuery 7  │   14.21 ms │                      13.09 ms │ +1.09x faster │
│ QQuery 8  │  384.07 ms │                     328.91 ms │ +1.17x faster │
│ QQuery 9  │  531.68 ms │                     465.07 ms │ +1.14x faster │
│ QQuery 10 │   74.56 ms │                      70.59 ms │ +1.06x faster │
│ QQuery 11 │   87.69 ms │                      81.76 ms │ +1.07x faster │
│ QQuery 12 │  276.65 ms │                     267.67 ms │     no change │
│ QQuery 13 │  360.99 ms │                     377.83 ms │     no change │
│ QQuery 14 │  282.98 ms │                     284.88 ms │     no change │
│ QQuery 15 │  268.82 ms │                     272.32 ms │     no change │
│ QQuery 16 │  623.33 ms │                     698.89 ms │  1.12x slower │
│ QQuery 17 │  624.35 ms │                     712.99 ms │  1.14x slower │
│ QQuery 18 │ 1260.58 ms │                    1297.29 ms │     no change │
│ QQuery 19 │   27.38 ms │                      27.29 ms │     no change │
│ QQuery 20 │  516.29 ms │                     518.94 ms │     no change │
│ QQuery 21 │  516.38 ms │                     518.17 ms │     no change │
│ QQuery 22 │  980.60 ms │                     992.06 ms │     no change │
│ QQuery 23 │ 3060.41 ms │                    3123.45 ms │     no change │
│ QQuery 24 │   41.52 ms │                      41.76 ms │     no change │
│ QQuery 25 │  110.19 ms │                     110.86 ms │     no change │
│ QQuery 26 │   41.57 ms │                      41.77 ms │     no change │
│ QQuery 27 │  512.95 ms │                     516.16 ms │     no change │
│ QQuery 28 │ 2899.49 ms │                    2927.52 ms │     no change │
│ QQuery 29 │   40.72 ms │                      40.95 ms │     no change │
│ QQuery 30 │  307.03 ms │                     313.55 ms │     no change │
│ QQuery 31 │  286.59 ms │                     289.87 ms │     no change │
│ QQuery 32 │  973.30 ms │                    1099.92 ms │  1.13x slower │
│ QQuery 33 │ 1485.01 ms │                    1492.82 ms │     no change │
│ QQuery 34 │ 1482.14 ms │                    1512.53 ms │     no change │
│ QQuery 35 │  278.49 ms │                     280.70 ms │     no change │
│ QQuery 36 │   67.55 ms │                      72.38 ms │  1.07x slower │
│ QQuery 37 │   35.31 ms │                      37.67 ms │  1.07x slower │
│ QQuery 38 │   40.35 ms │                      41.42 ms │     no change │
│ QQuery 39 │  138.13 ms │                     138.14 ms │     no change │
│ QQuery 40 │   13.81 ms │                      14.30 ms │     no change │
│ QQuery 41 │   13.55 ms │                      13.70 ms │     no change │
│ QQuery 42 │   13.03 ms │                      13.19 ms │     no change │
└───────────┴────────────┴───────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19298.00ms │
│ Total Time (in-exists-subquery-projection)   │ 19632.82ms │
│ Average Time (HEAD)                          │   448.79ms │
│ Average Time (in-exists-subquery-projection) │   456.58ms │
│ Queries Faster                               │          8 │
│ Queries Slower                               │          6 │
│ Queries with No Change                       │         29 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃         in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │          1.20 / 3.99 ±5.47 / 14.92 ms │          1.31 / 4.37 ±5.88 / 16.11 ms │  1.10x slower │
│ QQuery 1  │        11.64 / 11.84 ±0.10 / 11.92 ms │        11.99 / 12.47 ±0.39 / 12.96 ms │  1.05x slower │
│ QQuery 2  │        36.24 / 36.69 ±0.27 / 37.08 ms │        37.10 / 37.36 ±0.35 / 38.05 ms │     no change │
│ QQuery 3  │        33.09 / 34.03 ±0.74 / 35.06 ms │        32.32 / 32.89 ±0.39 / 33.30 ms │     no change │
│ QQuery 4  │    235.57 / 260.85 ±12.68 / 268.45 ms │    223.59 / 242.06 ±14.51 / 259.98 ms │ +1.08x faster │
│ QQuery 5  │     307.17 / 311.87 ±3.56 / 317.60 ms │     274.83 / 282.01 ±6.29 / 293.35 ms │ +1.11x faster │
│ QQuery 6  │           1.41 / 1.59 ±0.21 / 1.99 ms │           1.26 / 1.42 ±0.21 / 1.84 ms │ +1.11x faster │
│ QQuery 7  │        14.21 / 14.34 ±0.12 / 14.53 ms │        13.09 / 13.35 ±0.20 / 13.67 ms │ +1.07x faster │
│ QQuery 8  │     384.07 / 389.42 ±3.79 / 395.56 ms │     328.91 / 332.68 ±3.79 / 339.13 ms │ +1.17x faster │
│ QQuery 9  │    531.68 / 545.39 ±10.55 / 564.30 ms │     465.07 / 476.24 ±8.69 / 487.26 ms │ +1.15x faster │
│ QQuery 10 │        74.56 / 75.68 ±1.11 / 77.78 ms │        70.59 / 72.92 ±2.88 / 78.30 ms │     no change │
│ QQuery 11 │        87.69 / 88.16 ±0.47 / 88.89 ms │        81.76 / 82.95 ±0.88 / 84.23 ms │ +1.06x faster │
│ QQuery 12 │    276.65 / 289.47 ±15.63 / 319.97 ms │     267.67 / 276.85 ±7.80 / 289.63 ms │     no change │
│ QQuery 13 │    360.99 / 374.63 ±10.24 / 385.15 ms │    377.83 / 388.21 ±12.07 / 410.08 ms │     no change │
│ QQuery 14 │     282.98 / 287.98 ±4.44 / 295.34 ms │     284.88 / 289.43 ±3.88 / 295.69 ms │     no change │
│ QQuery 15 │     268.82 / 275.63 ±4.21 / 280.65 ms │    272.32 / 284.96 ±10.60 / 303.59 ms │     no change │
│ QQuery 16 │    623.33 / 672.83 ±31.05 / 715.89 ms │    698.89 / 716.77 ±13.10 / 739.28 ms │  1.07x slower │
│ QQuery 17 │    624.35 / 638.11 ±17.47 / 669.64 ms │     712.99 / 727.49 ±8.53 / 739.22 ms │  1.14x slower │
│ QQuery 18 │ 1260.58 / 1293.90 ±34.40 / 1357.34 ms │ 1297.29 / 1357.92 ±66.03 / 1479.93 ms │     no change │
│ QQuery 19 │        27.38 / 31.10 ±6.13 / 43.31 ms │        27.29 / 29.74 ±3.82 / 37.35 ms │     no change │
│ QQuery 20 │    516.29 / 535.09 ±14.36 / 555.11 ms │    518.94 / 532.31 ±14.30 / 558.85 ms │     no change │
│ QQuery 21 │     516.38 / 525.79 ±6.21 / 533.41 ms │    518.17 / 538.28 ±10.56 / 548.29 ms │     no change │
│ QQuery 22 │  980.60 / 1007.40 ±17.01 / 1024.98 ms │  992.06 / 1003.90 ±12.29 / 1026.88 ms │     no change │
│ QQuery 23 │ 3060.41 / 3110.25 ±54.40 / 3201.96 ms │ 3123.45 / 3148.97 ±15.75 / 3165.81 ms │     no change │
│ QQuery 24 │        41.52 / 42.18 ±0.40 / 42.64 ms │       41.76 / 48.91 ±11.10 / 70.62 ms │  1.16x slower │
│ QQuery 25 │     110.19 / 112.79 ±4.02 / 120.76 ms │     110.86 / 113.56 ±4.05 / 121.59 ms │     no change │
│ QQuery 26 │        41.57 / 42.55 ±0.60 / 43.23 ms │        41.77 / 42.86 ±1.25 / 45.23 ms │     no change │
│ QQuery 27 │     512.95 / 520.09 ±5.10 / 528.45 ms │     516.16 / 524.93 ±7.59 / 536.02 ms │     no change │
│ QQuery 28 │ 2899.49 / 3042.84 ±80.83 / 3116.48 ms │ 2927.52 / 2954.34 ±23.04 / 2996.84 ms │     no change │
│ QQuery 29 │        40.72 / 43.40 ±4.65 / 52.68 ms │        40.95 / 41.61 ±0.89 / 43.28 ms │     no change │
│ QQuery 30 │    307.03 / 324.18 ±13.77 / 343.86 ms │     313.55 / 318.15 ±3.37 / 322.72 ms │     no change │
│ QQuery 31 │    286.59 / 314.60 ±17.59 / 337.62 ms │    289.87 / 318.48 ±21.92 / 352.77 ms │     no change │
│ QQuery 32 │  973.30 / 1000.58 ±29.59 / 1047.55 ms │ 1099.92 / 1137.87 ±26.16 / 1173.81 ms │  1.14x slower │
│ QQuery 33 │ 1485.01 / 1530.88 ±57.27 / 1631.87 ms │ 1492.82 / 1624.01 ±94.04 / 1752.34 ms │  1.06x slower │
│ QQuery 34 │ 1482.14 / 1526.91 ±40.79 / 1603.25 ms │ 1512.53 / 1583.94 ±55.35 / 1675.37 ms │     no change │
│ QQuery 35 │    278.49 / 318.32 ±60.53 / 437.89 ms │    280.70 / 306.97 ±28.11 / 344.62 ms │     no change │
│ QQuery 36 │        67.55 / 76.26 ±6.34 / 84.64 ms │        72.38 / 81.78 ±8.00 / 93.60 ms │  1.07x slower │
│ QQuery 37 │        35.31 / 35.84 ±0.49 / 36.47 ms │        37.67 / 38.99 ±1.65 / 42.20 ms │  1.09x slower │
│ QQuery 38 │        40.35 / 43.80 ±2.29 / 47.11 ms │        41.42 / 45.46 ±3.00 / 50.73 ms │     no change │
│ QQuery 39 │     138.13 / 148.09 ±7.76 / 158.89 ms │     138.14 / 154.05 ±9.14 / 163.14 ms │     no change │
│ QQuery 40 │        13.81 / 14.15 ±0.39 / 14.83 ms │        14.30 / 14.74 ±0.40 / 15.39 ms │     no change │
│ QQuery 41 │        13.55 / 14.38 ±1.32 / 17.00 ms │        13.70 / 14.56 ±1.17 / 16.87 ms │     no change │
│ QQuery 42 │        13.03 / 13.76 ±1.07 / 15.87 ms │        13.19 / 13.82 ±0.85 / 15.50 ms │     no change │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19981.62ms │
│ Total Time (in-exists-subquery-projection)   │ 20264.57ms │
│ Average Time (HEAD)                          │   464.69ms │
│ Average Time (in-exists-subquery-projection) │   471.27ms │
│ Queries Faster                               │          7 │
│ Queries Slower                               │          9 │
│ Queries with No Change                       │         27 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Resource Usage

clickbench_partitioned — base (merge-base)

Metric Value
Wall time 105.0s
Peak memory 12.5 GiB
Avg memory 4.4 GiB
CPU user 1021.7s
CPU sys 71.6s
Peak spill 0 B

clickbench_partitioned — branch

Metric Value
Wall time 105.0s
Peak memory 11.4 GiB
Avg memory 4.4 GiB
CPU user 1033.5s
CPU sys 77.3s
Peak spill 0 B

File an issue against this benchmark runner

@adriangb

Copy link
Copy Markdown
Contributor Author

run benchmark clickbench_partitioned
changed:
ref: 22651d2

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5688276356-2381-j7bvc 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing 22651d2 (22651d2) to 22651d2 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
changed:
  ref: "22651d24cc8196f3206e09a36a437eda9e766b87"

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing 22651d2 (22651d2) to 22651d2 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
changed:
  ref: "22651d24cc8196f3206e09a36a437eda9e766b87"
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ in-exists-subquery-projection ┃    Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 0  │    1.23 ms │                       1.25 ms │ no change │
│ QQuery 1  │   11.80 ms │                      12.12 ms │ no change │
│ QQuery 2  │   36.51 ms │                      36.42 ms │ no change │
│ QQuery 3  │   31.66 ms │                      31.24 ms │ no change │
│ QQuery 4  │  230.28 ms │                     232.46 ms │ no change │
│ QQuery 5  │  281.64 ms │                     283.62 ms │ no change │
│ QQuery 6  │    1.28 ms │                       1.29 ms │ no change │
│ QQuery 7  │   13.58 ms │                      13.50 ms │ no change │
│ QQuery 8  │  344.46 ms │                     337.76 ms │ no change │
│ QQuery 9  │  478.66 ms │                     467.02 ms │ no change │
│ QQuery 10 │   70.88 ms │                      70.85 ms │ no change │
│ QQuery 11 │   82.35 ms │                      81.44 ms │ no change │
│ QQuery 12 │  280.50 ms │                     277.76 ms │ no change │
│ QQuery 13 │  373.65 ms │                     390.72 ms │ no change │
│ QQuery 14 │  293.06 ms │                     292.45 ms │ no change │
│ QQuery 15 │  280.03 ms │                     279.83 ms │ no change │
│ QQuery 16 │  632.03 ms │                     638.69 ms │ no change │
│ QQuery 17 │  642.74 ms │                     640.74 ms │ no change │
│ QQuery 18 │ 1302.01 ms │                    1296.72 ms │ no change │
│ QQuery 19 │   27.73 ms │                      27.74 ms │ no change │
│ QQuery 20 │  521.43 ms │                     520.87 ms │ no change │
│ QQuery 21 │  524.12 ms │                     517.74 ms │ no change │
│ QQuery 22 │  995.97 ms │                     994.55 ms │ no change │
│ QQuery 23 │ 3077.88 ms │                    3092.56 ms │ no change │
│ QQuery 24 │   41.22 ms │                      41.75 ms │ no change │
│ QQuery 25 │  111.05 ms │                     111.86 ms │ no change │
│ QQuery 26 │   41.72 ms │                      41.84 ms │ no change │
│ QQuery 27 │  517.27 ms │                     514.51 ms │ no change │
│ QQuery 28 │ 2935.48 ms │                    2986.02 ms │ no change │
│ QQuery 29 │   41.56 ms │                      41.62 ms │ no change │
│ QQuery 30 │  320.24 ms │                     322.06 ms │ no change │
│ QQuery 31 │  285.33 ms │                     292.75 ms │ no change │
│ QQuery 32 │  980.39 ms │                     977.72 ms │ no change │
│ QQuery 33 │ 1549.25 ms │                    1522.71 ms │ no change │
│ QQuery 34 │ 1518.11 ms │                    1530.72 ms │ no change │
│ QQuery 35 │  298.07 ms │                     295.86 ms │ no change │
│ QQuery 36 │   67.73 ms │                      67.14 ms │ no change │
│ QQuery 37 │   37.42 ms │                      37.35 ms │ no change │
│ QQuery 38 │   42.89 ms │                      42.16 ms │ no change │
│ QQuery 39 │  151.46 ms │                     145.43 ms │ no change │
│ QQuery 40 │   14.82 ms │                      14.92 ms │ no change │
│ QQuery 41 │   14.32 ms │                      14.31 ms │ no change │
│ QQuery 42 │   13.99 ms │                      13.88 ms │ no change │
└───────────┴────────────┴───────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19517.83ms │
│ Total Time (in-exists-subquery-projection)   │ 19553.94ms │
│ Average Time (HEAD)                          │   453.90ms │
│ Average Time (in-exists-subquery-projection) │   454.74ms │
│ Queries Faster                               │          0 │
│ Queries Slower                               │          0 │
│ Queries with No Change                       │         43 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃         in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │          1.23 / 4.14 ±5.69 / 15.52 ms │          1.25 / 4.11 ±5.60 / 15.30 ms │     no change │
│ QQuery 1  │        11.80 / 12.28 ±0.24 / 12.47 ms │        12.12 / 12.39 ±0.24 / 12.78 ms │     no change │
│ QQuery 2  │        36.51 / 37.00 ±0.37 / 37.63 ms │        36.42 / 36.82 ±0.40 / 37.57 ms │     no change │
│ QQuery 3  │        31.66 / 32.17 ±0.60 / 33.29 ms │        31.24 / 31.73 ±0.43 / 32.32 ms │     no change │
│ QQuery 4  │     230.28 / 236.21 ±3.14 / 238.78 ms │     232.46 / 235.23 ±1.96 / 237.89 ms │     no change │
│ QQuery 5  │     281.64 / 284.45 ±2.94 / 288.70 ms │     283.62 / 285.58 ±3.04 / 291.63 ms │     no change │
│ QQuery 6  │           1.28 / 1.44 ±0.22 / 1.87 ms │           1.29 / 1.44 ±0.22 / 1.86 ms │     no change │
│ QQuery 7  │        13.58 / 13.68 ±0.10 / 13.84 ms │        13.50 / 13.74 ±0.14 / 13.88 ms │     no change │
│ QQuery 8  │     344.46 / 349.07 ±3.26 / 354.56 ms │     337.76 / 342.88 ±2.79 / 345.76 ms │     no change │
│ QQuery 9  │     478.66 / 484.98 ±4.52 / 490.45 ms │    467.02 / 487.49 ±11.49 / 499.46 ms │     no change │
│ QQuery 10 │        70.88 / 72.21 ±1.37 / 73.91 ms │        70.85 / 71.83 ±0.94 / 73.48 ms │     no change │
│ QQuery 11 │        82.35 / 83.14 ±0.67 / 84.20 ms │        81.44 / 81.78 ±0.24 / 82.12 ms │     no change │
│ QQuery 12 │     280.50 / 287.61 ±5.10 / 295.64 ms │     277.76 / 281.25 ±3.21 / 285.28 ms │     no change │
│ QQuery 13 │    373.65 / 390.12 ±13.85 / 411.36 ms │    390.72 / 402.02 ±13.15 / 427.49 ms │     no change │
│ QQuery 14 │     293.06 / 298.84 ±6.45 / 310.29 ms │     292.45 / 298.29 ±3.67 / 303.15 ms │     no change │
│ QQuery 15 │     280.03 / 287.86 ±5.98 / 295.17 ms │    279.83 / 301.78 ±26.76 / 354.12 ms │     no change │
│ QQuery 16 │     632.03 / 638.63 ±5.99 / 649.40 ms │     638.69 / 648.68 ±7.73 / 659.31 ms │     no change │
│ QQuery 17 │     642.74 / 647.91 ±2.97 / 651.19 ms │    640.74 / 654.68 ±11.60 / 673.53 ms │     no change │
│ QQuery 18 │ 1302.01 / 1327.64 ±16.19 / 1344.13 ms │ 1296.72 / 1341.55 ±35.85 / 1405.11 ms │     no change │
│ QQuery 19 │       27.73 / 34.07 ±10.87 / 55.72 ms │        27.74 / 31.57 ±6.75 / 45.04 ms │ +1.08x faster │
│ QQuery 20 │    521.43 / 532.23 ±11.01 / 548.89 ms │     520.87 / 529.17 ±5.58 / 537.94 ms │     no change │
│ QQuery 21 │     524.12 / 527.09 ±3.91 / 534.73 ms │     517.74 / 521.50 ±2.94 / 525.48 ms │     no change │
│ QQuery 22 │  995.97 / 1013.62 ±11.92 / 1032.13 ms │   994.55 / 1006.62 ±8.04 / 1019.90 ms │     no change │
│ QQuery 23 │ 3077.88 / 3134.16 ±45.41 / 3212.40 ms │ 3092.56 / 3136.31 ±41.13 / 3198.64 ms │     no change │
│ QQuery 24 │        41.22 / 45.78 ±3.86 / 50.97 ms │        41.75 / 46.60 ±5.60 / 55.88 ms │     no change │
│ QQuery 25 │     111.05 / 115.05 ±5.04 / 124.83 ms │     111.86 / 120.61 ±6.71 / 129.57 ms │     no change │
│ QQuery 26 │        41.72 / 43.41 ±3.00 / 49.40 ms │        41.84 / 42.89 ±0.83 / 43.89 ms │     no change │
│ QQuery 27 │    517.27 / 528.97 ±11.52 / 550.82 ms │    514.51 / 530.78 ±15.70 / 559.80 ms │     no change │
│ QQuery 28 │ 2935.48 / 2994.83 ±31.60 / 3027.39 ms │ 2986.02 / 3015.90 ±24.81 / 3050.03 ms │     no change │
│ QQuery 29 │        41.56 / 45.52 ±7.33 / 60.17 ms │       41.62 / 52.73 ±14.35 / 77.88 ms │  1.16x slower │
│ QQuery 30 │     320.24 / 325.66 ±5.35 / 333.56 ms │     322.06 / 324.19 ±2.37 / 328.37 ms │     no change │
│ QQuery 31 │    285.33 / 305.41 ±11.08 / 318.18 ms │    292.75 / 307.88 ±12.24 / 323.59 ms │     no change │
│ QQuery 32 │  980.39 / 1000.01 ±13.94 / 1021.61 ms │  977.72 / 1002.94 ±20.72 / 1040.38 ms │     no change │
│ QQuery 33 │  1549.25 / 1563.12 ±9.94 / 1574.46 ms │ 1522.71 / 1574.68 ±78.87 / 1730.83 ms │     no change │
│ QQuery 34 │ 1518.11 / 1553.66 ±25.06 / 1594.87 ms │ 1530.72 / 1581.90 ±44.50 / 1652.42 ms │     no change │
│ QQuery 35 │    298.07 / 329.39 ±51.57 / 432.33 ms │    295.86 / 345.71 ±83.32 / 512.00 ms │     no change │
│ QQuery 36 │        67.73 / 70.94 ±3.15 / 75.73 ms │        67.14 / 73.25 ±4.11 / 79.53 ms │     no change │
│ QQuery 37 │        37.42 / 43.44 ±4.53 / 50.52 ms │        37.35 / 44.63 ±5.37 / 50.99 ms │     no change │
│ QQuery 38 │        42.89 / 45.43 ±2.70 / 50.13 ms │        42.16 / 45.36 ±3.32 / 51.54 ms │     no change │
│ QQuery 39 │     151.46 / 161.45 ±8.09 / 171.66 ms │     145.43 / 155.55 ±5.12 / 158.78 ms │     no change │
│ QQuery 40 │        14.82 / 15.06 ±0.34 / 15.73 ms │        14.92 / 15.37 ±0.30 / 15.77 ms │     no change │
│ QQuery 41 │        14.32 / 14.66 ±0.36 / 15.15 ms │        14.31 / 14.49 ±0.12 / 14.67 ms │     no change │
│ QQuery 42 │        13.99 / 16.79 ±5.28 / 27.35 ms │        13.88 / 14.12 ±0.13 / 14.24 ms │ +1.19x faster │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19949.12ms │
│ Total Time (in-exists-subquery-projection)   │ 20068.00ms │
│ Average Time (HEAD)                          │   463.93ms │
│ Average Time (in-exists-subquery-projection) │   466.70ms │
│ Queries Faster                               │          2 │
│ Queries Slower                               │          1 │
│ Queries with No Change                       │         40 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Resource Usage

clickbench_partitioned — base (merge-base)

Metric Value
Wall time 105.0s
Peak memory 11.8 GiB
Avg memory 4.4 GiB
CPU user 1022.0s
CPU sys 73.1s
Peak spill 0 B

clickbench_partitioned — branch

Metric Value
Wall time 105.0s
Peak memory 11.9 GiB
Avg memory 4.5 GiB
CPU user 1019.1s
CPU sys 74.7s
Peak spill 0 B

File an issue against this benchmark runner

@adriangb

Copy link
Copy Markdown
Contributor Author

run benchmark clickbench_partitioned

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5688513263-2382-7p7sn 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned

Results will be posted here when complete


File an issue against this benchmark runner

@adriangb

Copy link
Copy Markdown
Contributor Author

I opened #25346 to add benchmarks

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (04f3d7d) to 22651d2 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ in-exists-subquery-projection ┃       Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ QQuery 0  │    1.23 ms │                       1.24 ms │    no change │
│ QQuery 1  │   12.21 ms │                      12.01 ms │    no change │
│ QQuery 2  │   36.32 ms │                      36.29 ms │    no change │
│ QQuery 3  │   31.15 ms │                      31.16 ms │    no change │
│ QQuery 4  │  234.75 ms │                     233.62 ms │    no change │
│ QQuery 5  │  278.75 ms │                     280.70 ms │    no change │
│ QQuery 6  │    1.27 ms │                       1.30 ms │    no change │
│ QQuery 7  │   13.59 ms │                      13.55 ms │    no change │
│ QQuery 8  │  341.48 ms │                     341.45 ms │    no change │
│ QQuery 9  │  481.47 ms │                     485.36 ms │    no change │
│ QQuery 10 │   70.57 ms │                      72.18 ms │    no change │
│ QQuery 11 │   82.05 ms │                      82.52 ms │    no change │
│ QQuery 12 │  276.59 ms │                     276.56 ms │    no change │
│ QQuery 13 │  381.07 ms │                     370.06 ms │    no change │
│ QQuery 14 │  297.10 ms │                     292.23 ms │    no change │
│ QQuery 15 │  284.37 ms │                     276.79 ms │    no change │
│ QQuery 16 │  632.54 ms │                     645.58 ms │    no change │
│ QQuery 17 │  637.24 ms │                     641.60 ms │    no change │
│ QQuery 18 │ 1315.39 ms │                    1318.01 ms │    no change │
│ QQuery 19 │   27.91 ms │                      27.82 ms │    no change │
│ QQuery 20 │  527.71 ms │                     518.94 ms │    no change │
│ QQuery 21 │  520.45 ms │                     520.10 ms │    no change │
│ QQuery 22 │ 1003.88 ms │                    1000.16 ms │    no change │
│ QQuery 23 │ 3123.06 ms │                    3147.83 ms │    no change │
│ QQuery 24 │   41.51 ms │                      41.59 ms │    no change │
│ QQuery 25 │  110.71 ms │                     112.05 ms │    no change │
│ QQuery 26 │   41.69 ms │                      41.88 ms │    no change │
│ QQuery 27 │  511.40 ms │                     523.35 ms │    no change │
│ QQuery 28 │ 2967.96 ms │                    2958.13 ms │    no change │
│ QQuery 29 │   41.70 ms │                      41.60 ms │    no change │
│ QQuery 30 │  324.31 ms │                     319.53 ms │    no change │
│ QQuery 31 │  296.24 ms │                     285.84 ms │    no change │
│ QQuery 32 │  965.73 ms │                     959.92 ms │    no change │
│ QQuery 33 │ 1511.77 ms │                    1509.37 ms │    no change │
│ QQuery 34 │ 1547.41 ms │                    1502.82 ms │    no change │
│ QQuery 35 │  298.56 ms │                     297.69 ms │    no change │
│ QQuery 36 │   69.13 ms │                      69.63 ms │    no change │
│ QQuery 37 │   37.05 ms │                      37.76 ms │    no change │
│ QQuery 38 │   41.41 ms │                      44.23 ms │ 1.07x slower │
│ QQuery 39 │  157.55 ms │                     162.07 ms │    no change │
│ QQuery 40 │   14.94 ms │                      15.39 ms │    no change │
│ QQuery 41 │   14.36 ms │                      14.12 ms │    no change │
│ QQuery 42 │   13.86 ms │                      13.77 ms │    no change │
└───────────┴────────────┴───────────────────────────────┴──────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19619.48ms │
│ Total Time (in-exists-subquery-projection)   │ 19577.80ms │
│ Average Time (HEAD)                          │   456.27ms │
│ Average Time (in-exists-subquery-projection) │   455.30ms │
│ Queries Faster                               │          0 │
│ Queries Slower                               │          1 │
│ Queries with No Change                       │         42 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃         in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │          1.23 / 4.13 ±5.65 / 15.43 ms │          1.24 / 4.08 ±5.55 / 15.18 ms │     no change │
│ QQuery 1  │        12.21 / 12.42 ±0.13 / 12.56 ms │        12.01 / 12.28 ±0.20 / 12.54 ms │     no change │
│ QQuery 2  │        36.32 / 36.94 ±0.44 / 37.34 ms │        36.29 / 36.98 ±0.68 / 37.92 ms │     no change │
│ QQuery 3  │        31.15 / 32.10 ±0.96 / 33.93 ms │        31.16 / 31.52 ±0.31 / 31.86 ms │     no change │
│ QQuery 4  │     234.75 / 236.69 ±1.35 / 238.23 ms │     233.62 / 235.87 ±2.17 / 239.89 ms │     no change │
│ QQuery 5  │     278.75 / 286.39 ±4.20 / 291.21 ms │     280.70 / 283.73 ±2.28 / 286.99 ms │     no change │
│ QQuery 6  │           1.27 / 1.45 ±0.26 / 1.95 ms │           1.30 / 1.44 ±0.21 / 1.85 ms │     no change │
│ QQuery 7  │        13.59 / 13.80 ±0.16 / 13.96 ms │        13.55 / 13.66 ±0.07 / 13.75 ms │     no change │
│ QQuery 8  │     341.48 / 346.06 ±3.50 / 352.02 ms │     341.45 / 344.53 ±2.28 / 347.87 ms │     no change │
│ QQuery 9  │     481.47 / 490.01 ±7.89 / 502.20 ms │    485.36 / 499.58 ±11.62 / 513.15 ms │     no change │
│ QQuery 10 │        70.57 / 73.16 ±3.82 / 80.60 ms │        72.18 / 72.95 ±0.93 / 74.69 ms │     no change │
│ QQuery 11 │        82.05 / 82.64 ±0.75 / 84.07 ms │        82.52 / 83.42 ±0.59 / 83.98 ms │     no change │
│ QQuery 12 │     276.59 / 280.43 ±2.22 / 283.01 ms │     276.56 / 284.75 ±5.68 / 292.93 ms │     no change │
│ QQuery 13 │     381.07 / 388.29 ±5.62 / 394.64 ms │    370.06 / 402.27 ±26.16 / 444.88 ms │     no change │
│ QQuery 14 │     297.10 / 299.48 ±2.07 / 302.97 ms │    292.23 / 301.89 ±10.69 / 322.13 ms │     no change │
│ QQuery 15 │     284.37 / 289.72 ±5.41 / 297.55 ms │    276.79 / 299.44 ±20.23 / 332.03 ms │     no change │
│ QQuery 16 │     632.54 / 642.46 ±5.98 / 649.04 ms │     645.58 / 651.35 ±4.50 / 656.99 ms │     no change │
│ QQuery 17 │     637.24 / 650.23 ±8.66 / 664.53 ms │    641.60 / 659.72 ±14.45 / 681.17 ms │     no change │
│ QQuery 18 │  1315.39 / 1329.18 ±9.86 / 1342.01 ms │ 1318.01 / 1350.02 ±28.61 / 1393.93 ms │     no change │
│ QQuery 19 │        27.91 / 34.87 ±9.03 / 51.08 ms │        27.82 / 36.09 ±8.37 / 46.78 ms │     no change │
│ QQuery 20 │    527.71 / 537.95 ±12.72 / 560.51 ms │     518.94 / 525.46 ±5.01 / 533.81 ms │     no change │
│ QQuery 21 │     520.45 / 524.73 ±3.61 / 529.87 ms │     520.10 / 528.82 ±6.19 / 537.29 ms │     no change │
│ QQuery 22 │  1003.88 / 1015.29 ±9.23 / 1025.34 ms │ 1000.16 / 1016.75 ±11.77 / 1031.32 ms │     no change │
│ QQuery 23 │ 3123.06 / 3141.06 ±11.84 / 3156.16 ms │ 3147.83 / 3180.12 ±27.22 / 3226.68 ms │     no change │
│ QQuery 24 │        41.51 / 44.98 ±5.16 / 55.03 ms │       41.59 / 53.43 ±11.05 / 71.75 ms │  1.19x slower │
│ QQuery 25 │     110.71 / 113.06 ±1.91 / 116.17 ms │     112.05 / 112.98 ±0.85 / 114.19 ms │     no change │
│ QQuery 26 │        41.69 / 42.11 ±0.37 / 42.70 ms │        41.88 / 44.77 ±3.36 / 51.36 ms │  1.06x slower │
│ QQuery 27 │     511.40 / 528.32 ±8.82 / 535.36 ms │     523.35 / 533.02 ±9.66 / 549.69 ms │     no change │
│ QQuery 28 │ 2967.96 / 3002.02 ±24.68 / 3030.66 ms │ 2958.13 / 2971.94 ±19.53 / 3010.44 ms │     no change │
│ QQuery 29 │        41.70 / 43.88 ±3.61 / 51.04 ms │        41.60 / 46.63 ±9.49 / 65.60 ms │  1.06x slower │
│ QQuery 30 │     324.31 / 327.33 ±4.23 / 335.65 ms │     319.53 / 325.09 ±5.20 / 333.62 ms │     no change │
│ QQuery 31 │     296.24 / 300.97 ±4.50 / 308.38 ms │     285.84 / 296.33 ±7.51 / 309.04 ms │     no change │
│ QQuery 32 │   965.73 / 984.01 ±17.14 / 1005.78 ms │    959.92 / 981.30 ±12.20 / 998.02 ms │     no change │
│ QQuery 33 │ 1511.77 / 1538.27 ±21.78 / 1570.34 ms │ 1509.37 / 1541.23 ±24.15 / 1575.11 ms │     no change │
│ QQuery 34 │ 1547.41 / 1562.41 ±12.65 / 1583.33 ms │ 1502.82 / 1550.39 ±31.07 / 1591.96 ms │     no change │
│ QQuery 35 │     298.56 / 307.26 ±7.35 / 316.35 ms │    297.69 / 315.95 ±29.57 / 374.83 ms │     no change │
│ QQuery 36 │        69.13 / 79.22 ±7.37 / 88.32 ms │        69.63 / 75.64 ±4.59 / 82.57 ms │     no change │
│ QQuery 37 │        37.05 / 40.32 ±3.79 / 47.17 ms │        37.76 / 42.78 ±3.00 / 46.02 ms │  1.06x slower │
│ QQuery 38 │        41.41 / 46.22 ±3.94 / 53.03 ms │        44.23 / 47.60 ±5.67 / 58.87 ms │     no change │
│ QQuery 39 │     157.55 / 162.17 ±3.53 / 167.04 ms │     162.07 / 170.57 ±7.07 / 181.04 ms │  1.05x slower │
│ QQuery 40 │        14.94 / 15.28 ±0.34 / 15.89 ms │        15.39 / 15.62 ±0.17 / 15.81 ms │     no change │
│ QQuery 41 │        14.36 / 16.93 ±4.14 / 25.18 ms │        14.12 / 16.40 ±3.70 / 23.77 ms │     no change │
│ QQuery 42 │        13.86 / 18.11 ±4.63 / 24.06 ms │        13.77 / 13.94 ±0.13 / 14.08 ms │ +1.30x faster │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19922.34ms │
│ Total Time (in-exists-subquery-projection)   │ 20012.34ms │
│ Average Time (HEAD)                          │   463.31ms │
│ Average Time (in-exists-subquery-projection) │   465.40ms │
│ Queries Faster                               │          1 │
│ Queries Slower                               │          5 │
│ Queries with No Change                       │         37 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Resource Usage

clickbench_partitioned — base (merge-base)

Metric Value
Wall time 100.0s
Peak memory 12.1 GiB
Avg memory 4.7 GiB
CPU user 1018.3s
CPU sys 73.9s
Peak spill 0 B

clickbench_partitioned — branch

Metric Value
Wall time 105.0s
Peak memory 10.8 GiB
Avg memory 4.1 GiB
CPU user 1021.0s
CPU sys 75.4s
Peak spill 0 B

File an issue against this benchmark runner

@kosiew kosiew left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adriangb,

Thanks for working on this. Reusing the exact hashable LeftMark join for projected IN / NOT IN is a nice improvement, and the added NULL-semantics coverage is helpful.

I found one blocking issue in the correlated NOT IN path. The expression-level nullability change can now make a LeftAnti join null-aware when there is more than one hash key, but physical planning only supports a single key for null-aware LeftAnti joins. I left a repro and suggested adding an execution regression test below.

I also left one non-blocking suggestion for the empty-subquery boundary on the new single-mark-join path.

&& join_keys_may_be_null(&join_filter, left.schema(), sub_query_alias.schema())?;
// Additionally, if no join key can be NULL on either side, we don't need
// null-aware semantics because NULLs cannot exist in the keys.
let null_aware = if join_type == JoinType::LeftAnti && in_predicate_opt.is_some() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this introduces a planning failure for correlated NOT IN when the nullable expression key is combined with another correlated equality key.

For example, SELECT id FROM o WHERE NULLIF(id, 1) NOT IN (SELECT id FROM r WHERE r.grp = o.grp) with non-nullable o(id, grp) and r(id, grp) now makes the LeftAnti join null-aware because NULLIF(id, 1) is nullable. The correlation adds grp as a second hash key, so physical planning rejects the resulting join with null_aware LeftAnti joins only support single column join key, got 2 columns.

This looks newly reachable through the expression-level nullability change. Could we preserve the correct correlated NOT IN semantics using a supported fallback or plan shape here? It would also be good to add this query as an execution regression test and assert that only the SQL-true rows are returned.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, confirmed. The query failed with got 2 columns. It plans again in fe408e3: a LeftAnti join with more than one key keeps the column test from main.

This does not give the correct result for your NULLIF example. The join has two keys and is not null-aware, so the k = 1 row stays, the same as on main. The test in subquery_projection.slt records this, with a comment that links apache/datafusion#25347. A correct plan needs a null-aware LeftAnti join with more than one key. apache/datafusion#25339 (approved) adds that. When it merges, I will remove this special case and update the expected output to the correct rows. I did not want to add a second fallback plan here, because apache/datafusion#25339 is the fix for this.

05)----ProjectionExec: expr=[CAST(id@0 AS Int64) as r3.id]
06)------DataSourceExec: partitions=1, partition_sizes=[1]

# `NULLIF(id, 1)` is NULL for `id = 1`, and `r3` has no NULL, so the answer is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we also add an empty-subquery case for the new single null-aware mark path using a typed nullable key expression, for example NULLIF(id, 1)?

In particular, it would be useful to assert that the NULL-key row produces false, not NULL, when the subquery is empty, and that the plan still uses a single mark join. The existing top-level NULL IN (empty) test covers the SQL result semantics, but it takes the legacy three-join path, so it does not protect this boundary of the new optimization.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in fe408e3

@jayzhan211

Copy link
Copy Markdown
Contributor

Thanks @adriangb , here is a suggestion:

Correlated NOT IN with a scalar-function key now fails to plan

The LeftAnti branch now reads nullability from the key expressions. Most scalar UDFs use the default return_field_from_args, which always says the result can be NULL (datafusion/expr/src/udf.rs). So a key like upper(s) over a NOT NULL column now turns on null_aware.

For a correlated NOT IN in WHERE, that join has 2+ keys (value + correlation). HashJoinExec rejects null-aware LeftAnti with more than one key, and null-aware joins can't fall back to a sort-merge join:

CREATE TABLE t1(k INT NOT NULL, s VARCHAR NOT NULL) AS VALUES (1, 'a');
CREATE TABLE t2(k INT NOT NULL, s VARCHAR NOT NULL) AS VALUES (1, 'B');
SELECT * FROM t1 WHERE upper(t1.s) NOT IN (SELECT t2.s FROM t2 WHERE t2.k = t1.k);
-- main: plans a plain LeftAnti and returns (1, 'a')
-- this PR: expected "null_aware LeftAnti joins only support single column join key"

Nullable columns already fail like this on main (#25347), but this change extends the failure to common function keys over non-nullable data. It also pins uncorrelated lower(s) NOT IN (...) over NOT NULL columns to a CollectLeft null-aware join for no correctness gain.

Suggest limiting the expression-level check on the LeftAnti path to the single-key case until #25347 is fixed:

     let null_aware = if join_type == JoinType::LeftAnti && in_predicate_opt.is_some() {
         let (equijoin_keys, residual_filter) = split_eq_and_noneq_join_predicate(
             join_filter.clone(),
             left.schema(),
             sub_query_alias.schema(),
         )?;
-        join_keys_may_be_null(
-            &equijoin_keys,
-            residual_filter.as_ref(),
-            left.schema(),
-            sub_query_alias.schema(),
-        )?
+        if equijoin_keys.len() == 1 {
+            join_keys_may_be_null(
+                &equijoin_keys,
+                residual_filter.as_ref(),
+                left.schema(),
+                sub_query_alias.schema(),
+            )?
+        } else {
+            // Null-aware LeftAnti supports a single key only (#25347); keep the
+            // previous column-based test so correlated NOT IN still plans.
+            join_filter_columns_may_be_null(&join_filter, left.schema(), sub_query_alias.schema())?
+        }
     } else {

Please also add an slt case with the correlated query above.

@adriangb

Copy link
Copy Markdown
Contributor Author

Thanks @jayzhan211, good catch. I applied your suggestion in fe408e3.

@adriangb

Copy link
Copy Markdown
Contributor Author

@jayzhan211 @kosiew could we merge the benchmarks in #25346 before this change so we can look at perf numbers?

@adriangb

Copy link
Copy Markdown
Contributor Author

run benchmarks

@adriangb

Copy link
Copy Markdown
Contributor Author

run benchmark projection_subquery

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5733511883-2454-qnwwc 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5733511883-2455-8pz9s 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark tpcds

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5733511883-2456-k65xr 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark tpch

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark tpch
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query     ┃     HEAD ┃ in-exists-subquery-projection ┃    Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 1  │ 41.24 ms │                      41.59 ms │ no change │
│ QQuery 2  │ 19.29 ms │                      19.25 ms │ no change │
│ QQuery 3  │ 29.31 ms │                      29.17 ms │ no change │
│ QQuery 4  │ 17.96 ms │                      17.93 ms │ no change │
│ QQuery 5  │ 36.45 ms │                      36.10 ms │ no change │
│ QQuery 6  │ 16.90 ms │                      16.78 ms │ no change │
│ QQuery 7  │ 41.58 ms │                      42.57 ms │ no change │
│ QQuery 8  │ 41.21 ms │                      41.53 ms │ no change │
│ QQuery 9  │ 50.83 ms │                      51.89 ms │ no change │
│ QQuery 10 │ 43.10 ms │                      42.93 ms │ no change │
│ QQuery 11 │ 13.96 ms │                      14.03 ms │ no change │
│ QQuery 12 │ 24.54 ms │                      25.06 ms │ no change │
│ QQuery 13 │ 41.51 ms │                      41.66 ms │ no change │
│ QQuery 14 │ 25.11 ms │                      25.04 ms │ no change │
│ QQuery 15 │ 31.88 ms │                      31.78 ms │ no change │
│ QQuery 16 │ 14.65 ms │                      14.55 ms │ no change │
│ QQuery 17 │ 76.84 ms │                      76.58 ms │ no change │
│ QQuery 18 │ 63.64 ms │                      61.50 ms │ no change │
│ QQuery 19 │ 34.14 ms │                      34.19 ms │ no change │
│ QQuery 20 │ 32.99 ms │                      33.09 ms │ no change │
│ QQuery 21 │ 58.25 ms │                      57.76 ms │ no change │
│ QQuery 22 │ 14.61 ms │                      14.46 ms │ no change │
└───────────┴──────────┴───────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Benchmark Summary                            ┃          ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 769.98ms │
│ Total Time (in-exists-subquery-projection)   │ 769.44ms │
│ Average Time (HEAD)                          │  35.00ms │
│ Average Time (in-exists-subquery-projection) │  34.97ms │
│ Queries Faster                               │        0 │
│ Queries Slower                               │        0 │
│ Queries with No Change                       │       22 │
│ Queries with Failure                         │        0 │
└──────────────────────────────────────────────┴──────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpch_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query     ┃                           HEAD ┃  in-exists-subquery-projection ┃    Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 1  │ 41.24 / 42.22 ±1.21 / 44.52 ms │ 41.59 / 42.46 ±0.98 / 44.12 ms │ no change │
│ QQuery 2  │ 19.29 / 19.66 ±0.34 / 20.27 ms │ 19.25 / 19.47 ±0.17 / 19.75 ms │ no change │
│ QQuery 3  │ 29.31 / 29.36 ±0.05 / 29.42 ms │ 29.17 / 29.47 ±0.30 / 29.96 ms │ no change │
│ QQuery 4  │ 17.96 / 18.13 ±0.13 / 18.32 ms │ 17.93 / 18.19 ±0.22 / 18.58 ms │ no change │
│ QQuery 5  │ 36.45 / 37.67 ±1.36 / 39.52 ms │ 36.10 / 36.84 ±0.75 / 38.27 ms │ no change │
│ QQuery 6  │ 16.90 / 16.97 ±0.05 / 17.06 ms │ 16.78 / 16.94 ±0.15 / 17.21 ms │ no change │
│ QQuery 7  │ 41.58 / 44.02 ±2.83 / 49.54 ms │ 42.57 / 44.94 ±3.08 / 50.96 ms │ no change │
│ QQuery 8  │ 41.21 / 41.66 ±0.32 / 42.18 ms │ 41.53 / 41.87 ±0.35 / 42.47 ms │ no change │
│ QQuery 9  │ 50.83 / 52.47 ±1.19 / 54.27 ms │ 51.89 / 52.18 ±0.18 / 52.41 ms │ no change │
│ QQuery 10 │ 43.10 / 43.91 ±0.95 / 45.76 ms │ 42.93 / 44.19 ±1.84 / 47.84 ms │ no change │
│ QQuery 11 │ 13.96 / 14.22 ±0.17 / 14.50 ms │ 14.03 / 14.78 ±0.73 / 16.13 ms │ no change │
│ QQuery 12 │ 24.54 / 25.00 ±0.36 / 25.63 ms │ 25.06 / 25.37 ±0.31 / 25.95 ms │ no change │
│ QQuery 13 │ 41.51 / 42.78 ±1.43 / 45.57 ms │ 41.66 / 42.05 ±0.29 / 42.49 ms │ no change │
│ QQuery 14 │ 25.11 / 25.33 ±0.13 / 25.49 ms │ 25.04 / 25.30 ±0.30 / 25.88 ms │ no change │
│ QQuery 15 │ 31.88 / 32.67 ±0.79 / 34.05 ms │ 31.78 / 32.12 ±0.20 / 32.30 ms │ no change │
│ QQuery 16 │ 14.65 / 14.96 ±0.21 / 15.31 ms │ 14.55 / 15.42 ±0.97 / 17.30 ms │ no change │
│ QQuery 17 │ 76.84 / 77.79 ±1.26 / 80.20 ms │ 76.58 / 78.73 ±1.37 / 80.47 ms │ no change │
│ QQuery 18 │ 63.64 / 63.97 ±0.22 / 64.28 ms │ 61.50 / 63.70 ±1.25 / 65.37 ms │ no change │
│ QQuery 19 │ 34.14 / 34.80 ±0.77 / 36.23 ms │ 34.19 / 35.72 ±1.78 / 38.13 ms │ no change │
│ QQuery 20 │ 32.99 / 33.80 ±0.78 / 35.01 ms │ 33.09 / 33.43 ±0.36 / 34.10 ms │ no change │
│ QQuery 21 │ 58.25 / 59.08 ±1.54 / 62.15 ms │ 57.76 / 59.37 ±1.53 / 61.81 ms │ no change │
│ QQuery 22 │ 14.61 / 14.82 ±0.13 / 14.96 ms │ 14.46 / 14.93 ±0.61 / 16.12 ms │ no change │
└───────────┴────────────────────────────────┴────────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Benchmark Summary                            ┃          ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 785.29ms │
│ Total Time (in-exists-subquery-projection)   │ 787.47ms │
│ Average Time (HEAD)                          │  35.70ms │
│ Average Time (in-exists-subquery-projection) │  35.79ms │
│ Queries Faster                               │        0 │
│ Queries Slower                               │        0 │
│ Queries with No Change                       │       22 │
│ Queries with Failure                         │        0 │
└──────────────────────────────────────────────┴──────────┘

Resource Usage

tpch — base (merge-base)

Metric Value
Wall time 5.0s
Peak memory 1.2 GiB
Avg memory 497.4 MiB
CPU user 22.2s
CPU sys 1.9s
Peak spill 0 B

tpch — branch

Metric Value
Wall time 5.0s
Peak memory 1.2 GiB
Avg memory 513.7 MiB
CPU user 22.3s
CPU sys 1.8s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark running (GKE) | trigger
Instance: c4a-highmem-16 (12 vCPU / 65 GiB) | Linux bench-c5733513330-2457-lf8h7 6.12.94+ #1 SMP Tue Aug 4 08:44:15 UTC 2026 aarch64 GNU/Linux

CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark projection_subquery

Results will be posted here when complete


File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark tpcds
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1  │    5.91 ms │                       5.81 ms │     no change │
│ QQuery 2  │   82.84 ms │                      81.87 ms │     no change │
│ QQuery 3  │   29.51 ms │                      29.01 ms │     no change │
│ QQuery 4  │  490.40 ms │                     495.12 ms │     no change │
│ QQuery 5  │   51.08 ms │                      51.38 ms │     no change │
│ QQuery 6  │   38.17 ms │                      37.02 ms │     no change │
│ QQuery 7  │   75.26 ms │                      76.04 ms │     no change │
│ QQuery 8  │   37.72 ms │                      37.71 ms │     no change │
│ QQuery 9  │   51.37 ms │                      53.35 ms │     no change │
│ QQuery 10 │   61.77 ms │                      62.11 ms │     no change │
│ QQuery 11 │  301.70 ms │                     305.33 ms │     no change │
│ QQuery 12 │   29.24 ms │                      29.64 ms │     no change │
│ QQuery 13 │  118.86 ms │                     120.11 ms │     no change │
│ QQuery 14 │  425.27 ms │                     424.86 ms │     no change │
│ QQuery 15 │   61.29 ms │                      59.40 ms │     no change │
│ QQuery 16 │    6.72 ms │                       6.47 ms │     no change │
│ QQuery 17 │   81.20 ms │                      81.11 ms │     no change │
│ QQuery 18 │  107.42 ms │                     106.65 ms │     no change │
│ QQuery 19 │   42.22 ms │                      41.85 ms │     no change │
│ QQuery 20 │   36.98 ms │                      37.26 ms │     no change │
│ QQuery 21 │   17.42 ms │                      17.43 ms │     no change │
│ QQuery 22 │   65.35 ms │                      68.80 ms │  1.05x slower │
│ QQuery 23 │  329.95 ms │                     333.30 ms │     no change │
│ QQuery 24 │  198.00 ms │                     200.28 ms │     no change │
│ QQuery 25 │  112.19 ms │                     110.93 ms │     no change │
│ QQuery 26 │   49.42 ms │                      50.01 ms │     no change │
│ QQuery 27 │    6.09 ms │                       6.18 ms │     no change │
│ QQuery 28 │   60.61 ms │                      60.13 ms │     no change │
│ QQuery 29 │   98.41 ms │                      98.89 ms │     no change │
│ QQuery 30 │   33.21 ms │                      33.59 ms │     no change │
│ QQuery 31 │  109.44 ms │                     110.36 ms │     no change │
│ QQuery 32 │   20.28 ms │                      20.54 ms │     no change │
│ QQuery 33 │   37.90 ms │                      38.36 ms │     no change │
│ QQuery 34 │   10.47 ms │                      10.77 ms │     no change │
│ QQuery 35 │   75.22 ms │                      73.77 ms │     no change │
│ QQuery 36 │    5.80 ms │                       6.04 ms │     no change │
│ QQuery 37 │    7.04 ms │                       7.20 ms │     no change │
│ QQuery 38 │   62.15 ms │                      64.33 ms │     no change │
│ QQuery 39 │   76.63 ms │                      75.79 ms │     no change │
│ QQuery 40 │   24.81 ms │                      24.54 ms │     no change │
│ QQuery 41 │   11.34 ms │                      11.52 ms │     no change │
│ QQuery 42 │   23.96 ms │                      24.38 ms │     no change │
│ QQuery 43 │    5.09 ms │                       5.52 ms │  1.08x slower │
│ QQuery 44 │    9.50 ms │                       9.77 ms │     no change │
│ QQuery 45 │   40.70 ms │                      42.76 ms │  1.05x slower │
│ QQuery 46 │   12.18 ms │                      12.03 ms │     no change │
│ QQuery 47 │  252.77 ms │                     244.12 ms │     no change │
│ QQuery 48 │   96.46 ms │                      98.05 ms │     no change │
│ QQuery 49 │   70.79 ms │                      70.80 ms │     no change │
│ QQuery 50 │   59.34 ms │                      59.92 ms │     no change │
│ QQuery 51 │   94.25 ms │                      94.38 ms │     no change │
│ QQuery 52 │   24.40 ms │                      24.22 ms │     no change │
│ QQuery 53 │   29.42 ms │                      29.71 ms │     no change │
│ QQuery 54 │   54.95 ms │                      54.45 ms │     no change │
│ QQuery 55 │   24.34 ms │                      23.70 ms │     no change │
│ QQuery 56 │   39.05 ms │                      38.88 ms │     no change │
│ QQuery 57 │  178.25 ms │                     178.71 ms │     no change │
│ QQuery 58 │  112.30 ms │                     112.58 ms │     no change │
│ QQuery 59 │  119.16 ms │                     118.41 ms │     no change │
│ QQuery 60 │   39.96 ms │                      39.15 ms │     no change │
│ QQuery 61 │   12.03 ms │                      11.48 ms │     no change │
│ QQuery 62 │   46.81 ms │                      46.53 ms │     no change │
│ QQuery 63 │   29.39 ms │                      30.14 ms │     no change │
│ QQuery 64 │  365.52 ms │                     364.07 ms │     no change │
│ QQuery 65 │  128.39 ms │                     130.47 ms │     no change │
│ QQuery 66 │   80.06 ms │                      81.64 ms │     no change │
│ QQuery 67 │  260.05 ms │                     261.41 ms │     no change │
│ QQuery 68 │   11.74 ms │                      12.02 ms │     no change │
│ QQuery 69 │   56.69 ms │                      58.03 ms │     no change │
│ QQuery 70 │  107.73 ms │                     105.72 ms │     no change │
│ QQuery 71 │   35.05 ms │                      35.31 ms │     no change │
│ QQuery 72 │ 1937.41 ms │                    1738.01 ms │ +1.11x faster │
│ QQuery 73 │   10.14 ms │                      10.06 ms │     no change │
│ QQuery 74 │  173.04 ms │                     175.84 ms │     no change │
│ QQuery 75 │  144.86 ms │                     145.49 ms │     no change │
│ QQuery 76 │   35.53 ms │                      35.19 ms │     no change │
│ QQuery 77 │   61.35 ms │                      60.84 ms │     no change │
│ QQuery 78 │  170.07 ms │                     171.55 ms │     no change │
│ QQuery 79 │   66.54 ms │                      67.02 ms │     no change │
│ QQuery 80 │  100.26 ms │                      97.81 ms │     no change │
│ QQuery 81 │   26.59 ms │                      26.32 ms │     no change │
│ QQuery 82 │   16.77 ms │                      16.48 ms │     no change │
│ QQuery 83 │   34.14 ms │                      35.12 ms │     no change │
│ QQuery 84 │   29.92 ms │                      30.04 ms │     no change │
│ QQuery 85 │  105.26 ms │                     104.57 ms │     no change │
│ QQuery 86 │   25.82 ms │                      25.80 ms │     no change │
│ QQuery 87 │   63.18 ms │                      63.73 ms │     no change │
│ QQuery 88 │   62.34 ms │                      62.08 ms │     no change │
│ QQuery 89 │   36.24 ms │                      35.45 ms │     no change │
│ QQuery 90 │   16.95 ms │                      16.89 ms │     no change │
│ QQuery 91 │   45.99 ms │                      46.13 ms │     no change │
│ QQuery 92 │   29.88 ms │                      29.78 ms │     no change │
│ QQuery 93 │   50.68 ms │                      51.58 ms │     no change │
│ QQuery 94 │   39.34 ms │                      38.57 ms │     no change │
│ QQuery 95 │   81.98 ms │                      81.41 ms │     no change │
│ QQuery 96 │   24.18 ms │                      24.13 ms │     no change │
│ QQuery 97 │   52.29 ms │                      52.35 ms │     no change │
│ QQuery 98 │   43.63 ms │                      44.29 ms │     no change │
│ QQuery 99 │   71.45 ms │                      70.69 ms │     no change │
└───────────┴────────────┴───────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 9522.81ms │
│ Total Time (in-exists-subquery-projection)   │ 9340.48ms │
│ Average Time (HEAD)                          │   96.19ms │
│ Average Time (in-exists-subquery-projection) │   94.35ms │
│ Queries Faster                               │         1 │
│ Queries Slower                               │         3 │
│ Queries with No Change                       │        95 │
│ Queries with Failure                         │         0 │
└──────────────────────────────────────────────┴───────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark tpcds_sf1.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃         in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 1  │           5.91 / 6.52 ±0.96 / 8.44 ms │           5.81 / 6.42 ±0.95 / 8.31 ms │     no change │
│ QQuery 2  │        82.84 / 83.34 ±0.41 / 84.04 ms │        81.87 / 82.17 ±0.22 / 82.46 ms │     no change │
│ QQuery 3  │        29.51 / 29.63 ±0.08 / 29.74 ms │        29.01 / 29.35 ±0.30 / 29.86 ms │     no change │
│ QQuery 4  │     490.40 / 505.00 ±8.76 / 514.30 ms │     495.12 / 502.27 ±9.81 / 521.07 ms │     no change │
│ QQuery 5  │        51.08 / 51.97 ±0.56 / 52.51 ms │        51.38 / 52.21 ±0.60 / 53.05 ms │     no change │
│ QQuery 6  │        38.17 / 38.56 ±0.42 / 39.13 ms │        37.02 / 37.71 ±0.72 / 38.92 ms │     no change │
│ QQuery 7  │        75.26 / 75.84 ±0.65 / 76.67 ms │        76.04 / 76.29 ±0.36 / 76.97 ms │     no change │
│ QQuery 8  │        37.72 / 38.95 ±2.11 / 43.17 ms │        37.71 / 39.45 ±2.12 / 43.52 ms │     no change │
│ QQuery 9  │        51.37 / 53.33 ±1.79 / 56.65 ms │        53.35 / 56.61 ±4.12 / 64.61 ms │  1.06x slower │
│ QQuery 10 │        61.77 / 62.47 ±0.46 / 63.11 ms │        62.11 / 62.86 ±0.43 / 63.34 ms │     no change │
│ QQuery 11 │     301.70 / 309.90 ±7.05 / 322.55 ms │     305.33 / 313.66 ±4.57 / 318.48 ms │     no change │
│ QQuery 12 │        29.24 / 29.77 ±0.57 / 30.83 ms │        29.64 / 30.00 ±0.24 / 30.37 ms │     no change │
│ QQuery 13 │     118.86 / 120.18 ±0.90 / 120.98 ms │     120.11 / 120.65 ±0.37 / 120.98 ms │     no change │
│ QQuery 14 │     425.27 / 434.43 ±6.12 / 442.17 ms │     424.86 / 428.53 ±3.84 / 435.22 ms │     no change │
│ QQuery 15 │        61.29 / 63.16 ±1.63 / 65.67 ms │        59.40 / 61.85 ±1.80 / 64.50 ms │     no change │
│ QQuery 16 │           6.72 / 7.07 ±0.32 / 7.69 ms │           6.47 / 6.78 ±0.24 / 7.19 ms │     no change │
│ QQuery 17 │        81.20 / 82.95 ±1.70 / 86.03 ms │        81.11 / 82.15 ±1.14 / 84.34 ms │     no change │
│ QQuery 18 │     107.42 / 109.38 ±2.32 / 113.86 ms │     106.65 / 108.42 ±1.32 / 110.51 ms │     no change │
│ QQuery 19 │        42.22 / 42.44 ±0.27 / 42.95 ms │        41.85 / 42.38 ±0.69 / 43.74 ms │     no change │
│ QQuery 20 │        36.98 / 37.97 ±0.92 / 39.64 ms │        37.26 / 37.82 ±0.55 / 38.80 ms │     no change │
│ QQuery 21 │        17.42 / 17.66 ±0.14 / 17.86 ms │        17.43 / 17.85 ±0.32 / 18.26 ms │     no change │
│ QQuery 22 │        65.35 / 66.64 ±0.88 / 67.71 ms │        68.80 / 69.48 ±0.46 / 70.10 ms │     no change │
│ QQuery 23 │     329.95 / 336.05 ±4.80 / 340.61 ms │     333.30 / 338.54 ±4.62 / 347.14 ms │     no change │
│ QQuery 24 │     198.00 / 201.23 ±2.24 / 204.11 ms │     200.28 / 204.95 ±2.92 / 208.90 ms │     no change │
│ QQuery 25 │     112.19 / 112.70 ±0.39 / 113.34 ms │     110.93 / 113.90 ±2.56 / 118.53 ms │     no change │
│ QQuery 26 │        49.42 / 51.22 ±1.66 / 54.36 ms │        50.01 / 51.54 ±2.30 / 56.12 ms │     no change │
│ QQuery 27 │           6.09 / 6.30 ±0.13 / 6.50 ms │           6.18 / 6.34 ±0.17 / 6.65 ms │     no change │
│ QQuery 28 │        60.61 / 62.45 ±1.86 / 65.87 ms │        60.13 / 61.10 ±0.56 / 61.84 ms │     no change │
│ QQuery 29 │       98.41 / 99.63 ±1.27 / 101.99 ms │       98.89 / 99.75 ±0.69 / 100.64 ms │     no change │
│ QQuery 30 │        33.21 / 34.93 ±2.91 / 40.73 ms │        33.59 / 35.86 ±3.32 / 42.46 ms │     no change │
│ QQuery 31 │     109.44 / 110.70 ±0.94 / 112.13 ms │     110.36 / 111.38 ±0.94 / 113.04 ms │     no change │
│ QQuery 32 │        20.28 / 20.51 ±0.15 / 20.72 ms │        20.54 / 21.07 ±0.36 / 21.68 ms │     no change │
│ QQuery 33 │        37.90 / 38.59 ±0.45 / 39.10 ms │        38.36 / 38.85 ±0.33 / 39.36 ms │     no change │
│ QQuery 34 │        10.47 / 10.79 ±0.25 / 11.12 ms │        10.77 / 12.05 ±2.34 / 16.72 ms │  1.12x slower │
│ QQuery 35 │        75.22 / 77.19 ±1.53 / 79.37 ms │        73.77 / 75.72 ±1.98 / 78.87 ms │     no change │
│ QQuery 36 │           5.80 / 5.91 ±0.19 / 6.29 ms │           6.04 / 6.37 ±0.17 / 6.52 ms │  1.08x slower │
│ QQuery 37 │           7.04 / 7.15 ±0.10 / 7.28 ms │           7.20 / 7.41 ±0.13 / 7.62 ms │     no change │
│ QQuery 38 │        62.15 / 64.93 ±1.79 / 67.76 ms │        64.33 / 65.22 ±0.92 / 66.73 ms │     no change │
│ QQuery 39 │        76.63 / 78.71 ±1.71 / 80.75 ms │        75.79 / 78.56 ±2.36 / 82.87 ms │     no change │
│ QQuery 40 │        24.81 / 25.38 ±0.41 / 25.99 ms │        24.54 / 26.28 ±1.44 / 28.87 ms │     no change │
│ QQuery 41 │        11.34 / 12.45 ±1.45 / 15.31 ms │        11.52 / 11.85 ±0.27 / 12.24 ms │     no change │
│ QQuery 42 │        23.96 / 24.52 ±0.51 / 25.30 ms │        24.38 / 24.58 ±0.15 / 24.81 ms │     no change │
│ QQuery 43 │           5.09 / 5.31 ±0.21 / 5.72 ms │           5.52 / 5.68 ±0.13 / 5.87 ms │  1.07x slower │
│ QQuery 44 │           9.50 / 9.72 ±0.15 / 9.91 ms │          9.77 / 9.98 ±0.11 / 10.09 ms │     no change │
│ QQuery 45 │        40.70 / 42.29 ±1.07 / 44.08 ms │        42.76 / 44.00 ±1.26 / 46.39 ms │     no change │
│ QQuery 46 │        12.18 / 12.62 ±0.32 / 13.12 ms │        12.03 / 12.31 ±0.25 / 12.72 ms │     no change │
│ QQuery 47 │     252.77 / 257.10 ±3.47 / 262.67 ms │     244.12 / 250.13 ±3.60 / 254.27 ms │     no change │
│ QQuery 48 │        96.46 / 98.00 ±1.29 / 99.62 ms │       98.05 / 98.64 ±1.02 / 100.67 ms │     no change │
│ QQuery 49 │        70.79 / 71.53 ±0.66 / 72.66 ms │        70.80 / 71.79 ±0.77 / 72.99 ms │     no change │
│ QQuery 50 │        59.34 / 61.46 ±2.83 / 67.05 ms │        59.92 / 63.42 ±4.00 / 70.74 ms │     no change │
│ QQuery 51 │        94.25 / 96.35 ±1.66 / 99.25 ms │        94.38 / 95.39 ±0.90 / 97.08 ms │     no change │
│ QQuery 52 │        24.40 / 24.77 ±0.51 / 25.77 ms │        24.22 / 24.94 ±1.04 / 27.01 ms │     no change │
│ QQuery 53 │        29.42 / 29.66 ±0.20 / 29.99 ms │        29.71 / 31.20 ±2.74 / 36.68 ms │  1.05x slower │
│ QQuery 54 │        54.95 / 57.88 ±3.03 / 63.53 ms │        54.45 / 55.57 ±1.32 / 58.13 ms │     no change │
│ QQuery 55 │        24.34 / 24.62 ±0.27 / 25.11 ms │        23.70 / 24.04 ±0.20 / 24.33 ms │     no change │
│ QQuery 56 │        39.05 / 39.74 ±0.36 / 40.01 ms │        38.88 / 39.51 ±0.63 / 40.67 ms │     no change │
│ QQuery 57 │     178.25 / 181.44 ±1.79 / 183.62 ms │     178.71 / 181.78 ±2.88 / 186.75 ms │     no change │
│ QQuery 58 │     112.30 / 113.15 ±0.70 / 113.95 ms │     112.58 / 114.90 ±2.41 / 119.17 ms │     no change │
│ QQuery 59 │     119.16 / 120.33 ±0.86 / 121.26 ms │     118.41 / 119.95 ±1.64 / 122.98 ms │     no change │
│ QQuery 60 │        39.96 / 40.27 ±0.20 / 40.59 ms │        39.15 / 39.61 ±0.38 / 40.27 ms │     no change │
│ QQuery 61 │        12.03 / 12.33 ±0.34 / 12.97 ms │        11.48 / 11.70 ±0.21 / 12.11 ms │ +1.05x faster │
│ QQuery 62 │        46.81 / 48.26 ±1.72 / 51.63 ms │        46.53 / 48.44 ±1.50 / 51.06 ms │     no change │
│ QQuery 63 │        29.39 / 30.26 ±0.96 / 32.09 ms │        30.14 / 30.65 ±0.68 / 31.94 ms │     no change │
│ QQuery 64 │     365.52 / 371.84 ±6.27 / 383.54 ms │     364.07 / 372.87 ±7.15 / 382.77 ms │     no change │
│ QQuery 65 │     128.39 / 129.66 ±0.72 / 130.43 ms │     130.47 / 132.66 ±1.75 / 134.87 ms │     no change │
│ QQuery 66 │        80.06 / 82.27 ±2.79 / 87.73 ms │        81.64 / 83.64 ±3.26 / 90.08 ms │     no change │
│ QQuery 67 │     260.05 / 265.20 ±3.31 / 270.44 ms │     261.41 / 265.83 ±3.58 / 271.87 ms │     no change │
│ QQuery 68 │        11.74 / 11.89 ±0.16 / 12.11 ms │        12.02 / 12.34 ±0.17 / 12.50 ms │     no change │
│ QQuery 69 │        56.69 / 56.97 ±0.26 / 57.29 ms │        58.03 / 58.33 ±0.38 / 59.08 ms │     no change │
│ QQuery 70 │     107.73 / 111.61 ±3.69 / 118.44 ms │     105.72 / 109.44 ±2.84 / 113.20 ms │     no change │
│ QQuery 71 │        35.05 / 35.71 ±0.48 / 36.37 ms │        35.31 / 35.85 ±0.30 / 36.13 ms │     no change │
│ QQuery 72 │ 1937.41 / 1962.74 ±18.97 / 1983.58 ms │ 1738.01 / 1827.88 ±59.32 / 1924.59 ms │ +1.07x faster │
│ QQuery 73 │        10.14 / 10.55 ±0.35 / 11.16 ms │        10.06 / 10.42 ±0.18 / 10.53 ms │     no change │
│ QQuery 74 │     173.04 / 178.91 ±4.93 / 185.23 ms │     175.84 / 181.56 ±3.06 / 184.86 ms │     no change │
│ QQuery 75 │     144.86 / 145.77 ±0.58 / 146.46 ms │     145.49 / 147.40 ±1.49 / 149.96 ms │     no change │
│ QQuery 76 │        35.53 / 37.41 ±2.55 / 42.41 ms │        35.19 / 35.82 ±0.45 / 36.36 ms │     no change │
│ QQuery 77 │        61.35 / 62.69 ±1.66 / 65.95 ms │        60.84 / 61.40 ±0.54 / 62.40 ms │     no change │
│ QQuery 78 │     170.07 / 174.59 ±2.62 / 177.90 ms │     171.55 / 176.72 ±5.11 / 185.62 ms │     no change │
│ QQuery 79 │        66.54 / 67.25 ±0.87 / 68.86 ms │        67.02 / 68.74 ±1.27 / 70.05 ms │     no change │
│ QQuery 80 │     100.26 / 105.01 ±4.80 / 113.73 ms │       97.81 / 98.89 ±1.01 / 100.54 ms │ +1.06x faster │
│ QQuery 81 │        26.59 / 27.92 ±1.87 / 31.62 ms │        26.32 / 26.82 ±0.50 / 27.64 ms │     no change │
│ QQuery 82 │        16.77 / 17.14 ±0.20 / 17.35 ms │        16.48 / 16.77 ±0.15 / 16.91 ms │     no change │
│ QQuery 83 │        34.14 / 34.57 ±0.31 / 35.09 ms │        35.12 / 35.46 ±0.19 / 35.70 ms │     no change │
│ QQuery 84 │        29.92 / 30.21 ±0.22 / 30.44 ms │        30.04 / 31.90 ±2.64 / 37.11 ms │  1.06x slower │
│ QQuery 85 │     105.26 / 108.26 ±3.06 / 113.53 ms │     104.57 / 107.40 ±3.09 / 113.41 ms │     no change │
│ QQuery 86 │        25.82 / 26.28 ±0.42 / 26.93 ms │        25.80 / 25.91 ±0.11 / 26.09 ms │     no change │
│ QQuery 87 │        63.18 / 64.38 ±1.02 / 65.48 ms │        63.73 / 64.43 ±0.77 / 65.75 ms │     no change │
│ QQuery 88 │        62.34 / 65.43 ±4.62 / 74.62 ms │        62.08 / 62.77 ±0.49 / 63.47 ms │     no change │
│ QQuery 89 │        36.24 / 36.64 ±0.34 / 37.12 ms │        35.45 / 35.93 ±0.51 / 36.83 ms │     no change │
│ QQuery 90 │        16.95 / 17.82 ±1.03 / 19.81 ms │        16.89 / 17.22 ±0.21 / 17.46 ms │     no change │
│ QQuery 91 │        45.99 / 46.43 ±0.42 / 47.21 ms │        46.13 / 46.63 ±0.38 / 47.08 ms │     no change │
│ QQuery 92 │        29.88 / 30.23 ±0.35 / 30.77 ms │        29.78 / 31.46 ±2.10 / 35.53 ms │     no change │
│ QQuery 93 │        50.68 / 52.39 ±1.32 / 54.74 ms │        51.58 / 53.79 ±2.27 / 57.81 ms │     no change │
│ QQuery 94 │        39.34 / 40.29 ±0.93 / 42.06 ms │        38.57 / 39.26 ±0.55 / 40.14 ms │     no change │
│ QQuery 95 │        81.98 / 83.16 ±0.83 / 84.43 ms │        81.41 / 82.17 ±0.56 / 83.02 ms │     no change │
│ QQuery 96 │        24.18 / 24.42 ±0.16 / 24.62 ms │        24.13 / 24.46 ±0.23 / 24.71 ms │     no change │
│ QQuery 97 │        52.29 / 53.15 ±1.30 / 55.69 ms │        52.35 / 53.66 ±1.73 / 56.90 ms │     no change │
│ QQuery 98 │        43.63 / 45.20 ±1.11 / 47.07 ms │        44.29 / 44.84 ±0.58 / 45.95 ms │     no change │
│ QQuery 99 │        71.45 / 72.68 ±1.04 / 74.53 ms │        70.69 / 71.72 ±0.71 / 72.39 ms │     no change │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 9712.30ms │
│ Total Time (in-exists-subquery-projection)   │ 9582.27ms │
│ Average Time (HEAD)                          │   98.10ms │
│ Average Time (in-exists-subquery-projection) │   96.79ms │
│ Queries Faster                               │         3 │
│ Queries Slower                               │         6 │
│ Queries with No Change                       │        90 │
│ Queries with Failure                         │         0 │
└──────────────────────────────────────────────┴───────────┘

Resource Usage

tpcds — base (merge-base)

Metric Value
Wall time 50.0s
Peak memory 2.0 GiB
Avg memory 1.4 GiB
CPU user 214.0s
CPU sys 5.5s
Peak spill 0 B

tpcds — branch

Metric Value
Wall time 50.0s
Peak memory 2.2 GiB
Avg memory 1.6 GiB
CPU user 208.8s
CPU sys 5.6s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark clickbench_partitioned
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Query     ┃       HEAD ┃ in-exists-subquery-projection ┃    Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ QQuery 0  │    1.24 ms │                       1.25 ms │ no change │
│ QQuery 1  │   11.96 ms │                      12.37 ms │ no change │
│ QQuery 2  │   36.74 ms │                      36.85 ms │ no change │
│ QQuery 3  │   31.85 ms │                      31.62 ms │ no change │
│ QQuery 4  │  240.81 ms │                     235.62 ms │ no change │
│ QQuery 5  │  278.35 ms │                     277.43 ms │ no change │
│ QQuery 6  │    1.30 ms │                       1.34 ms │ no change │
│ QQuery 7  │   13.57 ms │                      13.54 ms │ no change │
│ QQuery 8  │  342.44 ms │                     335.03 ms │ no change │
│ QQuery 9  │  484.32 ms │                     468.04 ms │ no change │
│ QQuery 10 │   70.71 ms │                      71.22 ms │ no change │
│ QQuery 11 │   81.29 ms │                      82.47 ms │ no change │
│ QQuery 12 │  274.53 ms │                     271.97 ms │ no change │
│ QQuery 13 │  376.56 ms │                     376.26 ms │ no change │
│ QQuery 14 │  294.05 ms │                     287.16 ms │ no change │
│ QQuery 15 │  295.87 ms │                     291.57 ms │ no change │
│ QQuery 16 │  638.89 ms │                     631.23 ms │ no change │
│ QQuery 17 │  633.76 ms │                     640.90 ms │ no change │
│ QQuery 18 │ 1301.50 ms │                    1292.64 ms │ no change │
│ QQuery 19 │   28.50 ms │                      28.04 ms │ no change │
│ QQuery 20 │  518.86 ms │                     518.49 ms │ no change │
│ QQuery 21 │  512.08 ms │                     522.78 ms │ no change │
│ QQuery 22 │  984.93 ms │                    1001.66 ms │ no change │
│ QQuery 23 │ 3078.42 ms │                    3086.29 ms │ no change │
│ QQuery 24 │   41.35 ms │                      41.17 ms │ no change │
│ QQuery 25 │  110.74 ms │                     111.16 ms │ no change │
│ QQuery 26 │   41.87 ms │                      41.53 ms │ no change │
│ QQuery 27 │  516.15 ms │                     518.15 ms │ no change │
│ QQuery 28 │ 2879.82 ms │                    2893.30 ms │ no change │
│ QQuery 29 │   41.92 ms │                      42.48 ms │ no change │
│ QQuery 30 │  314.01 ms │                     320.01 ms │ no change │
│ QQuery 31 │  284.07 ms │                     289.26 ms │ no change │
│ QQuery 32 │  977.49 ms │                     963.56 ms │ no change │
│ QQuery 33 │ 1476.81 ms │                    1490.06 ms │ no change │
│ QQuery 34 │ 1479.32 ms │                    1523.45 ms │ no change │
│ QQuery 35 │  304.42 ms │                     296.94 ms │ no change │
│ QQuery 36 │   69.51 ms │                      66.59 ms │ no change │
│ QQuery 37 │   36.93 ms │                      35.87 ms │ no change │
│ QQuery 38 │   41.52 ms │                      43.07 ms │ no change │
│ QQuery 39 │  136.37 ms │                     141.80 ms │ no change │
│ QQuery 40 │   14.65 ms │                      14.78 ms │ no change │
│ QQuery 41 │   14.36 ms │                      14.28 ms │ no change │
│ QQuery 42 │   14.12 ms │                      13.74 ms │ no change │
└───────────┴────────────┴───────────────────────────────┴───────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19327.96ms │
│ Total Time (in-exists-subquery-projection)   │ 19376.97ms │
│ Average Time (HEAD)                          │   449.49ms │
│ Average Time (in-exists-subquery-projection) │   450.63ms │
│ Queries Faster                               │          0 │
│ Queries Slower                               │          0 │
│ Queries with No Change                       │         43 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Distribution per query (min / mean ±stddev / max):

Comparing HEAD and in-exists-subquery-projection
--------------------
Benchmark clickbench_partitioned.json
--------------------
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Query     ┃                                  HEAD ┃         in-exists-subquery-projection ┃        Change ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ QQuery 0  │          1.24 / 4.18 ±5.69 / 15.56 ms │          1.25 / 4.17 ±5.65 / 15.47 ms │     no change │
│ QQuery 1  │        11.96 / 12.42 ±0.25 / 12.66 ms │        12.37 / 12.54 ±0.11 / 12.67 ms │     no change │
│ QQuery 2  │        36.74 / 37.15 ±0.32 / 37.52 ms │        36.85 / 37.12 ±0.20 / 37.46 ms │     no change │
│ QQuery 3  │        31.85 / 32.66 ±0.84 / 33.77 ms │        31.62 / 31.91 ±0.28 / 32.42 ms │     no change │
│ QQuery 4  │     240.81 / 242.94 ±1.78 / 244.95 ms │     235.62 / 240.97 ±5.42 / 248.17 ms │     no change │
│ QQuery 5  │     278.35 / 281.38 ±2.39 / 283.53 ms │     277.43 / 283.37 ±3.77 / 288.78 ms │     no change │
│ QQuery 6  │           1.30 / 1.46 ±0.25 / 1.95 ms │           1.34 / 1.52 ±0.26 / 2.04 ms │     no change │
│ QQuery 7  │        13.57 / 14.51 ±1.45 / 17.40 ms │        13.54 / 13.79 ±0.16 / 14.00 ms │ +1.05x faster │
│ QQuery 8  │     342.44 / 346.52 ±4.25 / 353.98 ms │     335.03 / 339.24 ±3.05 / 344.41 ms │     no change │
│ QQuery 9  │     484.32 / 488.17 ±2.11 / 490.36 ms │     468.04 / 482.02 ±9.05 / 490.95 ms │     no change │
│ QQuery 10 │        70.71 / 75.00 ±7.14 / 89.22 ms │        71.22 / 74.02 ±2.76 / 78.67 ms │     no change │
│ QQuery 11 │        81.29 / 81.55 ±0.47 / 82.49 ms │        82.47 / 83.24 ±0.42 / 83.70 ms │     no change │
│ QQuery 12 │     274.53 / 281.91 ±6.34 / 291.87 ms │    271.97 / 281.96 ±10.19 / 300.89 ms │     no change │
│ QQuery 13 │     376.56 / 389.97 ±9.52 / 403.47 ms │    376.26 / 386.81 ±10.95 / 403.72 ms │     no change │
│ QQuery 14 │     294.05 / 299.67 ±5.61 / 309.24 ms │     287.16 / 296.29 ±7.21 / 305.92 ms │     no change │
│ QQuery 15 │     295.87 / 300.98 ±3.80 / 305.19 ms │    291.57 / 303.31 ±10.09 / 315.76 ms │     no change │
│ QQuery 16 │     638.89 / 645.65 ±6.12 / 656.42 ms │    631.23 / 657.85 ±16.27 / 679.07 ms │     no change │
│ QQuery 17 │     633.76 / 644.75 ±7.14 / 655.40 ms │     640.90 / 649.14 ±7.77 / 662.93 ms │     no change │
│ QQuery 18 │ 1301.50 / 1325.33 ±16.01 / 1341.98 ms │ 1292.64 / 1335.07 ±24.35 / 1357.98 ms │     no change │
│ QQuery 19 │       28.50 / 43.71 ±25.80 / 94.81 ms │       28.04 / 35.28 ±13.72 / 62.71 ms │ +1.24x faster │
│ QQuery 20 │     518.86 / 525.40 ±6.55 / 537.21 ms │     518.49 / 528.68 ±7.09 / 535.76 ms │     no change │
│ QQuery 21 │     512.08 / 514.07 ±1.62 / 515.85 ms │     522.78 / 526.17 ±3.31 / 530.94 ms │     no change │
│ QQuery 22 │  984.93 / 1000.13 ±12.97 / 1021.72 ms │  1001.66 / 1007.04 ±4.97 / 1016.32 ms │     no change │
│ QQuery 23 │ 3078.42 / 3120.06 ±36.04 / 3176.89 ms │ 3086.29 / 3133.48 ±31.03 / 3182.30 ms │     no change │
│ QQuery 24 │       41.35 / 46.91 ±10.49 / 67.89 ms │        41.17 / 43.42 ±3.62 / 50.62 ms │ +1.08x faster │
│ QQuery 25 │     110.74 / 111.53 ±0.76 / 112.81 ms │    111.16 / 119.74 ±11.95 / 142.73 ms │  1.07x slower │
│ QQuery 26 │        41.87 / 44.52 ±3.73 / 51.74 ms │        41.53 / 42.27 ±0.89 / 43.93 ms │ +1.05x faster │
│ QQuery 27 │     516.15 / 523.35 ±6.98 / 535.71 ms │     518.15 / 527.85 ±5.76 / 533.20 ms │     no change │
│ QQuery 28 │ 2879.82 / 2906.74 ±18.53 / 2928.46 ms │ 2893.30 / 2927.19 ±20.49 / 2954.95 ms │     no change │
│ QQuery 29 │      41.92 / 57.89 ±31.24 / 120.38 ms │        42.48 / 49.79 ±6.10 / 57.32 ms │ +1.16x faster │
│ QQuery 30 │    314.01 / 326.65 ±10.61 / 343.48 ms │     320.01 / 327.98 ±4.40 / 332.93 ms │     no change │
│ QQuery 31 │     284.07 / 290.62 ±6.63 / 302.52 ms │     289.26 / 301.45 ±8.96 / 312.69 ms │     no change │
│ QQuery 32 │   977.49 / 996.47 ±15.46 / 1018.26 ms │     963.56 / 973.08 ±5.26 / 978.54 ms │     no change │
│ QQuery 33 │ 1476.81 / 1505.29 ±22.67 / 1543.63 ms │ 1490.06 / 1526.68 ±36.75 / 1596.26 ms │     no change │
│ QQuery 34 │ 1479.32 / 1551.97 ±45.81 / 1623.93 ms │ 1523.45 / 1582.93 ±75.63 / 1723.37 ms │     no change │
│ QQuery 35 │    304.42 / 320.47 ±18.45 / 344.75 ms │    296.94 / 350.52 ±77.46 / 502.18 ms │  1.09x slower │
│ QQuery 36 │        69.51 / 74.36 ±5.18 / 83.62 ms │      66.59 / 87.43 ±26.71 / 140.17 ms │  1.18x slower │
│ QQuery 37 │        36.93 / 40.04 ±3.02 / 43.76 ms │        35.87 / 37.32 ±2.07 / 41.42 ms │ +1.07x faster │
│ QQuery 38 │        41.52 / 45.55 ±3.91 / 52.79 ms │        43.07 / 44.55 ±1.19 / 46.69 ms │     no change │
│ QQuery 39 │     136.37 / 147.76 ±7.21 / 158.62 ms │     141.80 / 153.45 ±7.95 / 164.19 ms │     no change │
│ QQuery 40 │        14.65 / 16.57 ±1.94 / 19.78 ms │        14.78 / 15.08 ±0.26 / 15.54 ms │ +1.10x faster │
│ QQuery 41 │        14.36 / 14.73 ±0.49 / 15.68 ms │        14.28 / 16.28 ±3.59 / 23.45 ms │  1.10x slower │
│ QQuery 42 │        14.12 / 14.19 ±0.05 / 14.25 ms │        13.74 / 14.44 ±0.96 / 16.35 ms │     no change │
└───────────┴───────────────────────────────────────┴───────────────────────────────────────┴───────────────┘
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Benchmark Summary                            ┃            ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ Total Time (HEAD)                            │ 19745.19ms │
│ Total Time (in-exists-subquery-projection)   │ 19886.43ms │
│ Average Time (HEAD)                          │   459.19ms │
│ Average Time (in-exists-subquery-projection) │   462.48ms │
│ Queries Faster                               │          7 │
│ Queries Slower                               │          4 │
│ Queries with No Change                       │         32 │
│ Queries with Failure                         │          0 │
└──────────────────────────────────────────────┴────────────┘

Resource Usage

clickbench_partitioned — base (merge-base)

Metric Value
Wall time 100.0s
Peak memory 12.2 GiB
Avg memory 4.6 GiB
CPU user 1010.1s
CPU sys 68.2s
Peak spill 0 B

clickbench_partitioned — branch

Metric Value
Wall time 100.0s
Peak memory 11.4 GiB
Avg memory 4.4 GiB
CPU user 1012.3s
CPU sys 72.4s
Peak spill 0 B

File an issue against this benchmark runner

@adriangbot

Copy link
Copy Markdown

🤖 Benchmark completed (GKE) | trigger

Instance: c4a-highmem-16 (12 vCPU / 65 GiB)

Comparing in-exists-subquery-projection (3af8737) to 64871d9 (merge-base) diff

Run configuration
run benchmark projection_subquery
CPU Details (lscpu)
Architecture:                            aarch64
CPU op-mode(s):                          64-bit
Byte Order:                              Little Endian
CPU(s):                                  16
On-line CPU(s) list:                     0-15
Vendor ID:                               ARM
Model name:                              Neoverse-V2
Model:                                   1
Thread(s) per core:                      1
Core(s) per cluster:                     16
Socket(s):                               -
Cluster(s):                              1
Stepping:                                r0p1
BogoMIPS:                                2000.00
Flags:                                   fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm jscvt fcma lrcpc dcpop sha3 sm3 sm4 asimddp sha512 sve asimdfhm dit uscat ilrcpc flagm sb paca pacg dcpodp sve2 sveaes svepmull svebitperm svesha3 svesm4 flagm2 frint svei8mm svebf16 i8mm bf16 dgh rng bti
L1d cache:                               1 MiB (16 instances)
L1i cache:                               1 MiB (16 instances)
L2 cache:                                32 MiB (16 instances)
L3 cache:                                80 MiB (1 instance)
NUMA node(s):                            1
NUMA node0 CPU(s):                       0-15
Vulnerability Gather data sampling:      Not affected
Vulnerability Indirect target selection: Not affected
Vulnerability Itlb multihit:             Not affected
Vulnerability L1tf:                      Not affected
Vulnerability Mds:                       Not affected
Vulnerability Meltdown:                  Not affected
Vulnerability Mmio stale data:           Not affected
Vulnerability Reg file data sampling:    Not affected
Vulnerability Retbleed:                  Not affected
Vulnerability Spec rstack overflow:      Not affected
Vulnerability Spec store bypass:         Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:                Mitigation; __user pointer sanitization
Vulnerability Spectre v2:                Mitigation; CSV2, BHB
Vulnerability Srbds:                     Not affected
Vulnerability Tsa:                       Not affected
Vulnerability Tsx async abort:           Not affected
Vulnerability Vmscape:                   Not affected
Details

group                                             HEAD                                    in-exists-subquery-projection
-----                                             ----                                    -----------------------------
projection_subquery/q01_in_bare                   212.56  244.3±10.45ms        ? ?/sec    1.00   1149.3±9.98µs        ? ?/sec
projection_subquery/q02_in_coalesce               238.11  498.8±43.46ms        ? ?/sec    1.00      2.1±0.01ms        ? ?/sec
projection_subquery/q03_in_correlated_eq          2.57      4.2±0.04ms        ? ?/sec     1.00  1622.0±14.54µs        ? ?/sec
projection_subquery/q04_in_two_columns            196.18  368.8±16.48ms        ? ?/sec    1.00  1879.9±14.05µs        ? ?/sec
projection_subquery/q05_not_in_bare               214.38   240.2±8.99ms        ? ?/sec    1.00   1120.3±9.12µs        ? ?/sec
projection_subquery/q06_exists_correlated         1.02    946.1±8.67µs        ? ?/sec     1.00   932.0±10.53µs        ? ?/sec
projection_subquery/q07_in_correlated_residual    1.00    100.3±1.36ms        ? ?/sec     1.02    101.9±4.42ms        ? ?/sec

Resource Usage

projection_subquery — base (merge-base)

Metric Value
Wall time 395.2s
Peak memory 266.8 MiB
Avg memory 31.3 MiB
CPU user 234.4s
CPU sys 3.7s
Peak spill 0 B

projection_subquery — branch

Metric Value
Wall time 515.2s
Peak memory 272.4 MiB
Avg memory 27.4 MiB
CPU user 122.2s
CPU sys 8.8s
Peak spill 0 B

File an issue against this benchmark runner

@adriangb

adriangb commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

Benchmark summary for 3af87370c1. Every run compares it with the merge-base 64871d9.

projection_subquery, the suite this PR targets:

Query main this PR
q01 bare IN 244.3 ms 1.15 ms 213x
q02 COALESCE over IN 498.8 ms 2.1 ms 238x
q03 correlated IN, equality 4.2 ms 1.62 ms 2.6x
q04 two IN columns 368.8 ms 1.88 ms 196x
q05 bare NOT IN 240.2 ms 1.12 ms 214x
q06 correlated EXISTS 946 µs 932 µs 1.02x
q07 correlated IN, non-equality 100.3 ms 101.9 ms 1.02x

q06 and q07 are the controls. q07 keeps the three-join materialization, which this PR does not change, and #25336 covers it.

The other suites show no change:

Suite Queries Faster Slower Total main Total this PR
tpch sf1 22 0 0 770.0 ms 769.4 ms
tpcds sf1 99 1 3 9522.8 ms 9340.5 ms
clickbench partitioned 43 0 0 19328.0 ms 19377.0 ms

The counts are from the min table. The four tpcds queries that move are q22 (1.05x slower), q43 (1.08x), q45 (1.05x) and q72 (1.11x faster), and the total is lower on the branch. The same comparison one run earlier gave 99 of 99 "no change", so these are the noise of this runner.

An absolute reference against DuckDB 1.5.2 is now in the description, under "DuckDB comparison". The short form: main is 270x to 680x slower than DuckDB on the four quadratic shapes, this PR puts them at DuckDB's cost, and q07 stays 4.9x faster than DuckDB. All three engines give the same counts.

@jayzhan211 jayzhan211 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is another possible issue

Correlation that repeats the IN predicate → wrong NULLs (regression vs base, which returns FALSE). remove_duplicated_filter (decorrelate.rs:189) drops i.k = o.k, the scope key is lost, and the join is planned as an uncorrelated null-aware LeftMark; the raw mark is now exposed. The result can never be UNKNOWN here since every in-scope row has y = x.

Repro:

CREATE TABLE o(id INT, k INT) AS VALUES (1,1),(2,1),(NULL,1),(2,2),(NULL,3),(5,NULL),(9,9);
CREATE TABLE i(id INT, k INT) AS VALUES (1,1),(NULL,2),(7,1),(3,NULL);
-- k=3, k=9, k=NULL: expected false, PR gives NULL
SELECT o.id, o.k, o.k IN (SELECT i.k FROM i WHERE i.k = o.k) AS m FROM o ORDER BY k, id;
-- (NULL,1), (2,2): expected false, PR gives NULL
SELECT o.id, o.k, o.id IN (SELECT i.id FROM i WHERE i.id = o.id AND i.k = o.k) AS m FROM o ORDER BY k, id;
-- same root cause, wrong on main too: expected 3 rows, got 0
SELECT o.id, o.k FROM o WHERE o.k NOT IN (SELECT i.k FROM i WHERE i.k = o.k) ORDER BY k, id;

Fix (both repro queries then return the base results; please add them to subquery_projection.slt):

--- a/datafusion/optimizer/src/decorrelate.rs
+++ b/datafusion/optimizer/src/decorrelate.rs
@@ pub struct PullUpCorrelatedExpr {
     pub in_predicate_opt: Option<Expr>,
+    /// The subquery repeats the `IN` predicate as a correlation
+    /// (`x IN (SELECT y .. WHERE y = x)`), so the result is never UNKNOWN.
+    pub in_predicate_is_correlation: bool,
@@ fn f_up
+                    let num_filters = join_filters.len();
                     join_filters = remove_duplicated_filter(join_filters, in_predicate)?;
+                    self.in_predicate_is_correlation |= join_filters.len() < num_filters;
--- a/datafusion/optimizer/src/decorrelate_predicate_subquery.rs
+++ b/datafusion/optimizer/src/decorrelate_predicate_subquery.rs
@@ fn build_join
         let null_aware = match hashable_only_split {
+            Some(_) if pull_up.in_predicate_is_correlation => false,
             Some((equijoin_keys, residual_filter)) => join_keys_may_be_null(
@@
-    let null_aware = if join_type == JoinType::LeftAnti && in_predicate_opt.is_some() {
+    let null_aware = if join_type == JoinType::LeftAnti
+        && in_predicate_opt.is_some()
+        && !pull_up.in_predicate_is_correlation
+    {

Also initialize in_predicate_is_correlation: false in PullUpCorrelatedExpr::new

haohuaijin pushed a commit to haohuaijin/arrow-datafusion that referenced this pull request Sep 19, 2026
## Which issue does this PR close?

- This PR closes no issue. It is related to
apache#25341 and it prepares the
A/B measurement for apache#25338.

## Rationale for this change

An `IN`, `NOT IN` or `EXISTS` subquery in the `SELECT` list is much
slower than the same subquery in a `WHERE` clause.
A projected `IN` must return `NULL`, and not `false`, when there is no
match and the inner side holds a `NULL`.
The decorrelation therefore turns one projected `IN` into more than one
mark join.
A mark join with no hashable join predicate runs as a nested-loop join,
so the cost grows with the outer row count times the inner row count.
There is no benchmark suite that measures this shape today.

The benchmark bot compares a pull request against its merge base.
It can only report a change if the suite is present on both sides.
The suite must therefore land on `main` first, before the fix is
measured with it.

## What changes are included in this PR?

- A new declarative SQL benchmark suite, `projection_subquery`, with
seven queries. Each query is one shape:
  - `q01_in_bare`: bare uncorrelated `IN`.
- `q02_in_coalesce`: the same `IN` wrapped in `COALESCE`, which is the
common way to use the result.
  - `q03_in_correlated_eq`: `IN` correlated on an equality.
- `q04_in_two_columns`: two independent `IN` subqueries in one `SELECT`
list.
  - `q05_not_in_bare`: `NOT IN`.
- `q06_exists_correlated`: correlated `EXISTS`, which has no `NULL`
result and needs only one mark join.
- `q07_in_correlated_residual`: `IN` correlated on `<`. There is no
equality to hash on, so this query keeps the nested-loop plan. It is the
control: its time must not change when the hashable shapes get faster.
- Two small integer tables built inline by the suite load SQL, so the
suite needs no data step. Every 97th inner key is `NULL`, which keeps
three-valued logic in play. Set `PSQ_ROWS` to change the row count in
each table. The default is 30000.
- An aggregate over the projected boolean in every query, so the result
is two numbers and the measured cost is the plan and not the size of the
output.
- Checked-in result files, so `--result-mode validate` also proves that
a change to the decorrelation still returns the same rows. The counts
hold for the default `PSQ_ROWS`.
- `bench.sh` wiring: `./benchmarks/bench.sh data projection_subquery`
reports that there is no external data, and `./benchmarks/bench.sh run
projection_subquery` runs the suite.
- Documentation in `benchmarks/README.md` and in the suite table of
`benchmarks/sql_benchmarks/README.md`.

## What is the testing strategy for this PR?

This PR adds no product code, so there are no unit tests. It was
verified by running the suite.

`./benchmarks/bench.sh data projection_subquery` prints the no-data
message.
`./benchmarks/bench.sh run projection_subquery` builds `cargo bench
--bench sql` and completes with a time for each of the seven queries.
`--result-mode validate` passes on `main` and on the branch of
apache#25338, which shows that both
sides return the same rows.

Median of five iterations at the default `PSQ_ROWS` of 30000, on one
machine:

| Query | main | With apache#25338 |
| --- | --- | --- |
| `q01_in_bare` | 341 ms | 0.8 ms |
| `q02_in_coalesce` | 690 ms | 1.1 ms |
| `q03_in_correlated_eq` | 2.6 ms | 0.9 ms |
| `q04_in_two_columns` | 527 ms | 1.2 ms |
| `q05_not_in_bare` | 349 ms | 0.6 ms |
| `q06_exists_correlated` | 0.6 ms | 0.4 ms |
| `q07_in_correlated_residual` (control) | 66 ms | 63 ms |

The control query is unchanged, as expected, because it has no equality
to hash on.

## Are there any user-facing changes?

No. This PR adds benchmarks only.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…`IN` predicate

`x IN (SELECT y FROM .. WHERE y = x)` writes the `IN` equality a second
time, as a correlated filter. `remove_duplicated_filter` drops that filter,
because `build_join` adds the same equality back as the join filter. The
scope of the subquery is then gone, and the join looked uncorrelated and
null-aware, so a miss gave UNKNOWN.

The result of this shape is never UNKNOWN: every row the subquery keeps for
an outer row satisfies `y = x`, so `y` is not NULL there and the subquery
result is either empty or `{x}`. `PullUpCorrelatedExpr` now reports the
shape, and the mark join and the anti join stay plain for it.

A node above the dropped filter can still put a NULL into the value column,
and then the result is UNKNOWN again. An outer join, a union and a grouping
set do this, so the flag is cleared when the pull up passes one of them.
`f_up` walks the subquery bottom up, so every such node above the filter is
reached after it.

This also fixes apache#25480, which is
the same root cause in a `WHERE ... NOT IN` clause.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The new `subquery_projection.slt` section holds the three queries from the
review: the `IN` whose correlation is the `IN` predicate, the same with a
second correlation, and the `WHERE ... NOT IN` form. It also pins the plan,
which no longer says `null_aware`, and the `ROLLUP` shape, which still does
because the grouping set puts a NULL back into the value column. Every
expected value agrees with DuckDB 1.5.2.

Two unit tests cover the mark join and the anti join.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@adriangb
adriangb force-pushed the in-exists-subquery-projection branch from b2ca096 to 7bb69a5 Compare September 19, 2026 17:39
@adriangb

Copy link
Copy Markdown
Contributor Author

Thank you, this is a real regression and I fixed it in 7bb69a5. All three of your queries now give the base results, and the third one, which is wrong on main too, gives the correct three rows. That third case is #25480.

Your diagnosis is right, and I took your in_predicate_is_correlation flag. I added one thing to it: the flag on its own is not sufficient, because a node above the dropped filter can put a NULL back into the value column, and the result is UNKNOWN again. Two shapes reach that, and the flag alone turns both from correct into false:

-- ROLLUP adds a NULL row for `i.k`, so a miss is UNKNOWN
SELECT o.k, o.k IN (SELECT i.k FROM i WHERE i.k = o.k GROUP BY ROLLUP(i.k)) AS m FROM o;
-- an unmatched row of `a` gives a NULL `b.y`, so a miss is UNKNOWN
SELECT o.k, o.k IN (SELECT b.y FROM a LEFT JOIN (SELECT * FROM b WHERE b.y = o.k) AS b ON a.id = b.id) AS m FROM o;

So the flag is cleared again when the pull up passes an outer join, a union or a grouping set. f_up walks the subquery bottom up, so every such node above the filter is reached after it:

fn f_up(&mut self, plan: LogicalPlan) -> Result<Transformed<LogicalPlan>> {
    if self.in_predicate_is_correlation && plan_may_add_null_rows(&plan) {
        self.in_predicate_is_correlation = false;
    }

Tests, as asked, in subquery_projection.slt: your two projection queries, your WHERE ... NOT IN query, an EXPLAIN guard that shows the join is no longer null-aware, and the ROLLUP guard. Two unit tests cover the mark join and the anti join. Every expected value agrees with DuckDB 1.5.2.

I also ran a differential fuzz against DuckDB over 18 correlated IN / NOT IN shapes and 24 random table pairs: 0 mismatches on this branch, and it finds this bug within 3 trials on the merge base.

One note on the second shape above. Pulling a correlated filter out from under the nullable side of an outer join is wrong on main as well, and the guard only keeps that shape where this branch already had it; it does not fix it. For example with a(id) = (1),(2) and b(id, y) = (1,1),(2,2), o.k = 5 gives false on main and on this branch, where DuckDB and PostgreSQL give NULL. Filed separately as #25507; the EXISTS form there is wrong too, so it is not a three-valued-logic problem.

@adriangb
adriangb requested review from jayzhan211 and a balanced review from Copilot September 19, 2026 17:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The optimizer changes affect subtle three-valued logic and known null-aware join limitations, warranting final human review.

Review effort: Balanced
Findings: None

Resolved since last review (1)

The rule decided null-awareness with three special cases: a flag that
`PullUpCorrelatedExpr` set when it dropped a duplicated correlation and
cleared again for a list of plan nodes, a switch to a weaker column test
when the null-aware `LeftAnti` executor could not take the join, and an
empty key list that selected that weaker test at the constant `IN` call.

Replace them with one question. `IN` can only be UNKNOWN when its value
or the subquery output can be NULL inside the scope of an outer row. A
correlated conjunct such as `y = x` is never TRUE for a NULL, so a key it
compares cannot be NULL in scope. `PullUpCorrelatedExpr` now records every
correlated conjunct before it drops the duplicated one, and `JoinKeys`
asks the two sides of the `IN` predicate for their nullability against
those conjuncts. A correlation key that is NULL only empties the scope,
so it never makes the join null-aware.

The executor limits are then applied in one place. A `NOT IN` whose value
can be NULL and whose join has more than one key becomes a null-aware
`LeftMark` join, which takes any number of keys, plus a filter on the
mark. A `NOT IN` with a residual filter becomes the mark joins that
materialize its three-valued result, the same plan as a projected `IN`.
Both shapes failed to plan or gave wrong results before. The constant
value projection now applies to correlated subqueries too, since the
mark join accepts the correlation as a second key.

The guard for a grouping set above the dropped filter is gone with the
flag. That query is wrong on `main` for `EXISTS` as well, because the
pull up moves the filter above the aggregate; that is
apache#25519.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@adriangb
adriangb force-pushed the in-exists-subquery-projection branch from 984bfbd to fb08efa Compare September 19, 2026 23:11
adriangb and others added 4 commits September 20, 2026 11:05
`cargo doc` runs with `-D warnings`, and the doc comment of the public
field `correlated_filters` made an intra-doc link to
`remove_duplicated_filter`, which is private. The link resolves only
because CI passes `--document-private-items`, so rustdoc reports
`rustdoc::private_intra_doc_links` and the job fails. Name the function
in backticks instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`joins.slt` pins the plan of this shape, but no test gave its result. The
tables there hold no NULL in the subquery column, so `main` answers that
query correctly and the plan change alone looks like a cost with no gain.

Put one NULL in the subquery column and `main` drops every row: its
null-aware anti join does not apply the residual filter when it looks for
a NULL, so it treats a subquery that is empty for most outer rows as one
that holds a NULL for all of them. DuckDB 1.5.2 gives the two rows that
this test expects.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The fallback for an `IN` whose join keeps a residual filter built three
mark joins. The first says whether the value matched. The other two, both
without a join predicate, say whether the subquery gives a NULL and
whether it gives any row at all, and the caller combined them as
`has_null OR (value IS NULL AND non_empty)`.

One join answers both. Its filter keeps a subquery row when the subquery
value is NULL, or when the outer value is NULL and the row is in scope at
all. For a value that is not NULL the mark reads `has_null`. For a value
that is NULL it reads `non_empty`, which is the weaker fact that case
needs and which `has_null` implies. `IS NULL` is two-valued on both
sides, so neither test adds an UNKNOWN of its own.

`build_join` gains the extra predicate, and `mark_join_with_alias` lets
the caller own the alias so that it can name the aliased subquery column.
No result changes: only `EXPLAIN` expectations move, and the `CASE` loses
its disjunction. A differential fuzz of 560 correlated `IN` and `NOT IN`
queries against DuckDB 1.5.2 finds no mismatch, and the same fuzz finds
98 on the merge base.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… rule

The merged UNKNOWN join names the value in its join filter. When that
value is an outer reference of an enclosing subquery it cannot resolve
there, and `build_join` reads it as a constant because `column_refs`
does not report an outer reference. The query is not supported either
way, but the optimizer reported a schema error instead of the plain
"not implemented" that the physical planner gives.

Decline the rewrite for such a value, which restores that message for a
scalar subquery and for an `IN` that is nested in one. An `EXISTS` that
holds the same predicate still reports a schema error; it is unsupported
on `main` as well, and is not made worse by the merge beyond the text.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Projected IN subqueries plan two extra nested-loop mark joins per subquery and become quadratic

7 participants