Skip to content

Cost-free covering scans for values computed from index columns - #4875

Draft
hatyo wants to merge 1 commit into
FoundationDB:mainfrom
hatyo:covering-sum-pushdown
Draft

hatyo wants to merge 1 commit into
FoundationDB:mainfrom
hatyo:covering-sum-pushdown

Conversation

@hatyo

@hatyo hatyo commented Nov 11, 2026

Copy link
Copy Markdown
Contributor

Let a covering scan serve values computed from index columns (e.g. SELECT a + b over an index on (a, b)) instead of forcing a record fetch.

Replace `ScanWithFetchMatchCandidate.isOfPushableTypesOrConstant` and the
hand-rolled `mapMaybe` fold in `pushValueThroughFetch` with a `MaxMatchMap`
against the record a covering scan can provide.

The removed guard allowed only `FieldValue` and `RecordConstructorValue`, so
any arithmetic in a projection forced a record fetch: `SELECT a + b` over an
index on `(a, b)` could not use a covering scan even though both columns are
in the index entry. The guard was added by be93a3c (FoundationDB#2090) to keep a
`VersionValue` from being pushed; `VersionValue` was since deleted in
f737921 (FoundationDB#4101), and `__ROW_VERSION` is now a `PseudoField` that is excluded
upstream by `IndexKeyValueToPartialRecord.Builder.validateField`, so the guard
no longer protected anything.

`IndexEntryToLogicalRecord` gains a `providedRecordValue`: the base record with
each carried field reading itself and the rest absent, keyed by ordinal so that
escaped SQL identifiers line up with their descriptor names. The translated
value is simplified, so a correlated `q0.x` does not come back as a field of a
record constructed over `q0`.

Plan expectations are updated across the yamsql files; queries only gain
covering scans. Where a union now runs over covering legs the fetch sits above
the union.
@hatyo
hatyo force-pushed the covering-sum-pushdown branch from ac4b4c9 to a98731d Compare November 11, 2026 10:10
@github-actions

Copy link
Copy Markdown

📊 Metrics Diff Analysis Report

Summary

  • New queries: 6
  • Dropped queries: 0
  • Plan changed + metrics changed: 66
  • Plan unchanged + metrics changed: 34
ℹ️ About this analysis

This automated analysis compares query planner metrics between the base branch and this PR. It categorizes changes into:

  • New queries: Queries added in this PR
  • Dropped queries: Queries removed in this PR. These should be reviewed to ensure we are not losing coverage.
  • Plan changed + metrics changed: The query plan has changed along with planner metrics.
  • Metrics only changed: Same plan but different metrics

The last category in particular may indicate planner regressions that should be investigated.

New Queries

Count of new queries by file:

  • yaml-tests/src/test/resources/covering-sum-pushdown.metrics.yaml: 1
  • yaml-tests/src/test/resources/row-version-pushdown.metrics.yaml: 5

Plan and Metrics Changed

These queries experienced both plan and metrics changes. This generally indicates that there was some planner change
that means the planning for this query may be substantially different. Some amount of query plan metrics change is expected,
but the reviewer should still validate that these changes are not excessive.

Total: 66 queries

Statistical Summary (Plan and Metrics Changed)

task_count:

  • Average change: +63.5
  • Average regression: +65.6
  • Median change: +18
  • Median regression: +18
  • Standard deviation: 77.2
  • Standard deviation of regressions: 77.4
  • Range: -4 to +261
  • Range of regressions: +18 to +261
  • Queries changed: 66
  • Queries regressed: 64

task_count % change distribution (66 queries, bin = 2%):

       Range                                  n
------------  ------------------------------  ---
  [-2%, +0%)  ██                              2
  [+0%, +2%)  █                               1
  [+2%, +4%)  ██████████████████████████████  25
  [+4%, +6%)  ███████████                     9
  [+6%, +8%)  █████████████                   11
 [+8%, +10%)  ████                            3
[+10%, +12%)  ██████                          5
[+12%, +14%)  █████                           4
[+14%, +16%)  █                               1
[+16%, +18%)                                  0
[+18%, +20%)  █                               1
[+20%, +22%)                                  0
[+22%, +24%)                                  0
[+24%, +26%)                                  0
[+26%, +28%)  ██                              2
[+28%, +30%)  ██                              2

transform_count:

  • Average change: +9.3
  • Average regression: +9.3
  • Median change: +3
  • Median regression: +3
  • Standard deviation: 10.6
  • Standard deviation of regressions: 10.6
  • Range: +3 to +36
  • Range of regressions: +3 to +36
  • Queries changed: 64
  • Queries regressed: 64

transform_count % change distribution (64 queries, bin = 2%):

       Range                                  n
------------  ------------------------------  ---
  [+0%, +2%)  ████████████                    12
  [+2%, +4%)  ██████████████████████████████  31
  [+4%, +6%)  ███████                         7
  [+6%, +8%)  █████████                       9
 [+8%, +10%)                                  0
[+10%, +12%)  █                               1
[+12%, +14%)                                  0
[+14%, +16%)  ████                            4

transform_yield_count:

  • Average change: +3.0
  • Average regression: +3.0
  • Median change: +1
  • Median regression: +1
  • Standard deviation: 3.0
  • Standard deviation of regressions: 3.0
  • Range: +1 to +10
  • Range of regressions: +1 to +10
  • Queries changed: 64
  • Queries regressed: 64

transform_yield_count % change distribution (64 queries, bin = 2%):

       Range                                  n
------------  ------------------------------  ---
  [+0%, +2%)  ███████████                     11
  [+2%, +4%)  ██████████████████████████████  29
  [+4%, +6%)  ███████████                     11
  [+6%, +8%)  ███████                         7
 [+8%, +10%)                                  0
[+10%, +12%)  ██                              2
[+12%, +14%)                                  0
[+14%, +16%)  ██                              2
[+16%, +18%)  ██                              2

insert_new_count:

  • Average change: +10.2
  • Average regression: +10.2
  • Median change: +3
  • Median regression: +3
  • Standard deviation: 11.8
  • Standard deviation of regressions: 11.8
  • Range: +3 to +39
  • Range of regressions: +3 to +39
  • Queries changed: 64
  • Queries regressed: 64

insert_new_count % change distribution (64 queries, bin = 2%):

       Range                                  n
------------  ------------------------------  ---
  [+0%, +2%)  ██                              1
  [+2%, +4%)  ███████████                     7
  [+4%, +6%)  ██████████████████████████████  19
  [+6%, +8%)  ███████████                     7
 [+8%, +10%)  ███████████                     7
[+10%, +12%)  ███████████                     7
[+12%, +14%)  ████████                        5
[+14%, +16%)  ███                             2
[+16%, +18%)  ██                              1
[+18%, +20%)  ██████                          4
[+20%, +22%)                                  0
[+22%, +24%)                                  0
[+24%, +26%)                                  0
[+26%, +28%)                                  0
[+28%, +30%)                                  0
[+30%, +32%)                                  0
[+32%, +34%)  ███                             2
[+34%, +36%)                                  0
[+36%, +38%)  ███                             2

insert_reused_count:

  • Average change: +2.2
  • Average regression: +2.2
  • Median change: +3
  • Median regression: +3
  • Standard deviation: 1.3
  • Standard deviation of regressions: 1.3
  • Range: +1 to +5
  • Range of regressions: +1 to +5
  • Queries changed: 12
  • Queries regressed: 12

insert_reused_count % change distribution (12 queries, bin = 2%):

         Range                                  n
--------------  ------------------------------  ---
    [+2%, +4%)  ███████████████                 2
    [+4%, +6%)                                  0
    [+6%, +8%)                                  0
   [+8%, +10%)                                  0
  [+10%, +12%)                                  0
  [+12%, +14%)  ████████                        1
  [+14%, +16%)                                  0
  [+16%, +18%)                                  0
  [+18%, +20%)                                  0
  [+20%, +22%)                                  0
  [+22%, +24%)                                  0
  [+24%, +26%)  ██████████████████████████████  4
  [+26%, +28%)                                  0
  [+28%, +30%)                                  0
  [+30%, +32%)                                  0
  [+32%, +34%)  ███████████████                 2
  [+34%, +36%)                                  0
  [+36%, +38%)                                  0
  [+38%, +40%)                                  0
  [+40%, +42%)                                  0
  [+42%, +44%)                                  0
  [+44%, +46%)                                  0
  [+46%, +48%)                                  0
  [+48%, +50%)                                  0
  [+50%, +52%)                                  0
  [+52%, +54%)                                  0
  [+54%, +56%)                                  0
  [+56%, +58%)                                  0
  [+58%, +60%)                                  0
  [+60%, +62%)  ███████████████                 2
  [+62%, +64%)                                  0
  [+64%, +66%)                                  0
  [+66%, +68%)                                  0
  [+68%, +70%)                                  0
  [+70%, +72%)                                  0
  [+72%, +74%)                                  0
  [+74%, +76%)                                  0
  [+76%, +78%)                                  0
  [+78%, +80%)                                  0
  [+80%, +82%)                                  0
  [+82%, +84%)                                  0
  [+84%, +86%)                                  0
  [+86%, +88%)                                  0
  [+88%, +90%)                                  0
  [+90%, +92%)                                  0
  [+92%, +94%)                                  0
  [+94%, +96%)                                  0
  [+96%, +98%)                                  0
 [+98%, +100%)                                  0
[+100%, +102%)                                  0
[+102%, +104%)                                  0
[+104%, +106%)                                  0
[+106%, +108%)                                  0
[+108%, +110%)                                  0
[+110%, +112%)                                  0
[+112%, +114%)                                  0
[+114%, +116%)                                  0
[+116%, +118%)                                  0
[+118%, +120%)                                  0
[+120%, +122%)                                  0
[+122%, +124%)                                  0
[+124%, +126%)  ████████                        1

Significant Regressions (Plan and Metrics Changed)

There were 11 outliers detected. Outlier queries have a significant regression in at least one field. Statistically, this represents either an increase of more than two standard deviations above the mean or a large absolute increase (e.g., 100).

  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:57: EXPLAIN with recursive c1 as ( select id, parent from t1 where parent = -1 union all select b.id, b.parent from c1 as a, t1 as b where a.id = b.parent) select id from c1
    • old explain: RUNION-DFS PREORDER q0 { ISCAN(PARENTIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.ID EQUALS _.PARENT | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID)
    • new explain: RUNION-DFS PREORDER q0 { ISCAN(PARENTIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.ID EQUALS _.PARENT | MAP _ } | MAP (_.ID AS ID)
    • task_count: 1839 -> 2061 (+222)
    • transform_count: 397 -> 428 (+31)
    • transform_yield_count: 124 -> 133 (+9)
    • insert_new_count: 260 -> 295 (+35)
  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:72: EXPLAIN with recursive c1 as ( select id, parent from t1 where parent = -1 union all select b.id, b.parent from c1 as a, t1 as b where a.id = b.parent) traversal order post_order select id from c1
    • old explain: RUNION-DFS POSTORDER q0 { ISCAN(PARENTIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.ID EQUALS _.PARENT | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID)
    • new explain: RUNION-DFS POSTORDER q0 { ISCAN(PARENTIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.ID EQUALS _.PARENT | MAP _ } | MAP (_.ID AS ID)
    • task_count: 1800 -> 2022 (+222)
    • transform_count: 391 -> 422 (+31)
    • transform_yield_count: 121 -> 130 (+9)
    • insert_new_count: 252 -> 286 (+34)
  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:103: EXPLAIN with recursive c1 as ( select id, parent from t1 where id = 250 union all select b.id, b.parent from c1 as a, t1 as b where a.parent = b.id) select id from c1
    • old explain: RUNION-DFS PREORDER q0 { ISCAN(CHILDIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.PARENT EQUALS _.ID | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID)
    • new explain: RUNION-DFS PREORDER q0 { ISCAN(CHILDIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.PARENT EQUALS _.ID | MAP _ } | MAP (_.ID AS ID)
    • task_count: 2185 -> 2407 (+222)
    • transform_count: 439 -> 470 (+31)
    • transform_yield_count: 135 -> 144 (+9)
    • insert_new_count: 315 -> 350 (+35)
  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:134: EXPLAIN with recursive c1 as ( select id, parent from t1 where id = 250 union all select b.id, b.parent from c1 as a, t1 as b where a.parent = b.id) traversal order pre_order select id from c1
    • old explain: RUNION-DFS PREORDER q0 { ISCAN(CHILDIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.PARENT EQUALS _.ID | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID)
    • new explain: RUNION-DFS PREORDER q0 { ISCAN(CHILDIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.PARENT EQUALS _.ID | MAP _ } | MAP (_.ID AS ID)
    • task_count: 2146 -> 2368 (+222)
    • transform_count: 433 -> 464 (+31)
    • transform_yield_count: 132 -> 141 (+9)
    • insert_new_count: 305 -> 339 (+34)
  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:149: EXPLAIN with recursive c1 as ( select id, parent from t1 where id = 250 union all select b.id, b.parent from c1 as a, t1 as b where a.parent = b.id) traversal order post_order select id from c1
    • old explain: RUNION-DFS POSTORDER q0 { ISCAN(CHILDIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.PARENT EQUALS _.ID | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID)
    • new explain: RUNION-DFS POSTORDER q0 { ISCAN(CHILDIDX [EQUALS promote(@c14 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.PARENT EQUALS _.ID | MAP _ } | MAP (_.ID AS ID)
    • task_count: 2146 -> 2368 (+222)
    • transform_count: 433 -> 464 (+31)
    • transform_yield_count: 132 -> 141 (+9)
    • insert_new_count: 305 -> 339 (+34)
  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:164: EXPLAIN with recursive allDescendants as ( with recursive ancestorsOf250 as ( select id, parent from t1 where id = 250 union all select b.id, b.parent from ancestorsOf250 as a, t1 as b where a.parent = b.id) select id, parent from ancestorsOf250 union all select b.id, b.parent from allDescendants as a, t1 as b where a.id = b.parent) select id, parent from allDescendants
    • old explain: RUNION-DFS PREORDER q0 { RUNION-DFS PREORDER q1 { ISCAN(CHILDIDX [EQUALS promote(@c19 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q1.PARENT EQUALS _.ID | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID, _.PARENT AS PARENT) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.ID EQUALS _.PARENT | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID, _.PARENT AS PARENT)
    • new explain: RUNION-DFS PREORDER q0 { RUNION-DFS PREORDER q1 { ISCAN(CHILDIDX [EQUALS promote(@c19 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q1.PARENT EQUALS _.ID | MAP _ } | MAP (_.ID AS ID, _.PARENT AS PARENT) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.ID EQUALS _.PARENT | MAP _ } | MAP (_.ID AS ID, _.PARENT AS PARENT)
    • task_count: 3415 -> 3637 (+222)
    • transform_count: 705 -> 736 (+31)
    • transform_yield_count: 207 -> 216 (+9)
    • insert_new_count: 499 -> 534 (+35)
  • yaml-tests/src/test/resources/recursive-cte.metrics.yaml:184: EXPLAIN with recursive allDescendants as ( with recursive ancestorsOf250 as ( select id, parent from t1 where id = 250 union all select b.id, b.parent from ancestorsOf250 as a, t1 as b where a.parent = b.id) traversal order post_order select id, parent from ancestorsOf250 union all select b.id, b.parent from allDescendants as a, t1 as b where a.id = b.parent) traversal order post_order select id, parent from allDescendants
    • old explain: RUNION-DFS POSTORDER q0 { RUNION-DFS POSTORDER q1 { ISCAN(CHILDIDX [EQUALS promote(@c19 AS LONG)]) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q1.PARENT EQUALS _.ID | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID, _.PARENT AS PARENT) } { RECURSIVE COVERING(PARENTIDX <,> -> [ID: KEY:[1], PARENT: KEY:[0]]) | FILTER q0.ID EQUALS _.PARENT | MAP (_.ID AS ID, _.PARENT AS PARENT) } | MAP (_.ID AS ID, _.PARENT AS PARENT)
    • new explain: RUNION-DFS POSTORDER q0 { RUNION-DFS POSTORDER q1 { ISCAN(CHILDIDX [EQUALS promote(@c19 AS LONG)]) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q1.PARENT EQUALS _.ID | MAP _ } | MAP (_.ID AS ID, _.PARENT AS PARENT) } { RECURSIVE COVERING(CHILDIDX <,> -> [ID: KEY:[0], PARENT: KEY:[1]]) | FILTER q0.ID EQUALS _.PARENT | MAP _ } | MAP (_.ID AS ID, _.PARENT AS PARENT)
    • task_count: 3125 -> 3347 (+222)
    • transform_count: 664 -> 695 (+31)
    • transform_yield_count: 193 -> 202 (+9)
    • insert_new_count: 447 -> 481 (+34)
  • yaml-tests/src/test/resources/sql-functions.metrics.yaml:40: EXPLAIN select col1 + 10, col2 from f1(103, 'b');
    • old explain: ISCAN(T1_IDX1 [EQUALS @c11, [LESS_THAN promote(@c9 AS LONG)]]) | MAP (_.COL1 + @c3 AS _0, _.COL2 AS COL2)
    • new explain: COVERING(T1_IDX1 [EQUALS @c11, [LESS_THAN promote(@c9 AS LONG)]] -> [COL1: KEY:[1], COL2: KEY:[0], COL3: KEY:[2]]) | MAP (_.COL1 + @c3 AS _0, _.COL2 AS COL2)
    • task_count: 984 -> 1136 (+152)
    • transform_count: 240 -> 256 (+16)
    • transform_yield_count: 86 -> 96 (+10)
    • insert_new_count: 122 -> 142 (+20)
    • insert_reused_count: 4 -> 9 (+5)
  • yaml-tests/src/test/resources/sql-functions.metrics.yaml:203: EXPLAIN select * from f3(103, 'b', 4)
    • old explain: ISCAN(T1_IDX1 <,>) | FILTER promote(_.COL3 AS LONG) EQUALS promote(@c9 AS LONG) | FLATMAP q0 -> { ISCAN(T1_IDX1 [EQUALS @c7, [LESS_THAN promote(@c5 AS LONG)]]) AS q1 RETURN (q1.COL1 AS COL1, q1.COL2 AS COL2, q0.COL3 AS COL3) }
    • new explain: COVERING(T1_IDX1 <,> -> [COL1: KEY:[1], COL2: KEY:[0], COL3: KEY:[2]]) | FILTER promote(_.COL3 AS LONG) EQUALS promote(@c9 AS LONG) | FETCH | FLATMAP q0 -> { ISCAN(T1_IDX1 [EQUALS @c7, [LESS_THAN promote(@c5 AS LONG)]]) AS q1 RETURN (q1.COL1 AS COL1, q1.COL2 AS COL2, q0.COL3 AS COL3) }
    • task_count: 2293 -> 2554 (+261)
    • transform_count: 534 -> 570 (+36)
    • transform_yield_count: 218 -> 227 (+9)
    • insert_new_count: 454 -> 493 (+39)
    • insert_reused_count: 24 -> 27 (+3)
  • yaml-tests/src/test/resources/sql-functions.metrics.yaml:231: EXPLAIN select * from f4(103, 'b', 2, 2)
    • old explain: ISCAN(T1_IDX1 <,>) | FILTER promote(_.COL3 AS LONG) EQUALS promote(@c9 AS LONG) + promote(@c9 AS LONG) | FLATMAP q0 -> { ISCAN(T1_IDX1 [EQUALS @c7, [LESS_THAN promote(@c5 AS LONG)]]) AS q1 RETURN (q1.COL1 AS COL1, q1.COL2 AS COL2, q0.COL3 AS COL3) }
    • new explain: COVERING(T1_IDX1 <,> -> [COL1: KEY:[1], COL2: KEY:[0], COL3: KEY:[2]]) | FILTER promote(_.COL3 AS LONG) EQUALS promote(@c9 AS LONG) + promote(@c9 AS LONG) | FETCH | FLATMAP q0 -> { ISCAN(T1_IDX1 [EQUALS @c7, [LESS_THAN promote(@c5 AS LONG)]]) AS q1 RETURN (q1.COL1 AS COL1, q1.COL2 AS COL2, q0.COL3 AS COL3) }
    • task_count: 4174 -> 4435 (+261)
    • transform_count: 923 -> 959 (+36)
    • transform_yield_count: 387 -> 396 (+9)
    • insert_new_count: 1127 -> 1166 (+39)
    • insert_reused_count: 103 -> 106 (+3)
  • yaml-tests/src/test/resources/sql-functions.metrics.yaml:246: EXPLAIN select * from f4(a => 103, b => 'b', c => 2, d => 2)
    • old explain: ISCAN(T1_IDX1 <,>) | FILTER promote(_.COL3 AS LONG) EQUALS promote(@c15 AS LONG) + promote(@c15 AS LONG) | FLATMAP q0 -> { ISCAN(T1_IDX1 [EQUALS @c11, [LESS_THAN promote(@c7 AS LONG)]]) AS q1 RETURN (q1.COL1 AS COL1, q1.COL2 AS COL2, q0.COL3 AS COL3) }
    • new explain: COVERING(T1_IDX1 <,> -> [COL1: KEY:[1], COL2: KEY:[0], COL3: KEY:[2]]) | FILTER promote(_.COL3 AS LONG) EQUALS promote(@c15 AS LONG) + promote(@c15 AS LONG) | FETCH | FLATMAP q0 -> { ISCAN(T1_IDX1 [EQUALS @c11, [LESS_THAN promote(@c7 AS LONG)]]) AS q1 RETURN (q1.COL1 AS COL1, q1.COL2 AS COL2, q0.COL3 AS COL3) }
    • task_count: 4174 -> 4435 (+261)
    • transform_count: 923 -> 959 (+36)
    • transform_yield_count: 387 -> 396 (+9)
    • insert_new_count: 1127 -> 1166 (+39)
    • insert_reused_count: 103 -> 106 (+3)

Minor Changes (Plan and Metrics Changed)

In addition, there were 55 queries with minor changes.

Only Metrics Changed

These queries experienced only metrics changes without any plan changes. If these metrics have substantially changed,
then a planner change has been made which affects planner performance but does not correlate with any new outcomes,
which could indicate a regression.

Total: 34 queries

Statistical Summary (Only Metrics Changed)

task_count:

  • Average change: +26.2
  • Average regression: +27.1
  • Median change: +18
  • Median regression: +18
  • Standard deviation: 20.3
  • Standard deviation of regressions: 20.0
  • Range: -2 to +93
  • Range of regressions: +9 to +93
  • Queries changed: 33
  • Queries regressed: 32

task_count % change distribution (33 queries, bin = 2%):

     Range                                  n
----------  ------------------------------  ---
[-2%, +0%)  █                               1
[+0%, +2%)  ███████                         5
[+2%, +4%)  ██████████████████████████████  21
[+4%, +6%)  █████████                       6

transform_count:

  • Average change: +3.9
  • Average regression: +3.9
  • Median change: +3
  • Median regression: +3
  • Standard deviation: 2.7
  • Standard deviation of regressions: 2.7
  • Range: +2 to +13
  • Range of regressions: +2 to +13
  • Queries changed: 32
  • Queries regressed: 32

transform_count % change distribution (32 queries, bin = 2%):

     Range                                  n
----------  ------------------------------  ---
[+0%, +2%)  ██████████████████████████      15
[+2%, +4%)  ██████████████████████████████  17

transform_yield_count:

  • Average change: +1.3
  • Average regression: +1.3
  • Median change: +1
  • Median regression: +1
  • Standard deviation: 0.6
  • Standard deviation of regressions: 0.6
  • Range: +1 to +3
  • Range of regressions: +1 to +3
  • Queries changed: 32
  • Queries regressed: 32

transform_yield_count % change distribution (32 queries, bin = 2%):

     Range                                  n
----------  ------------------------------  ---
[+0%, +2%)  ██████████████████████████████  23
[+2%, +4%)  ████████████                    9

insert_new_count:

  • Average change: +3.7
  • Average regression: +3.7
  • Median change: +3
  • Median regression: +3
  • Standard deviation: 1.9
  • Standard deviation of regressions: 1.9
  • Range: +1 to +9
  • Range of regressions: +1 to +9
  • Queries changed: 34
  • Queries regressed: 34

insert_new_count % change distribution (34 queries, bin = 2%):

      Range                                  n
-----------  ------------------------------  ---
 [+0%, +2%)  ██████████████                  5
 [+2%, +4%)  █████████████████████████       9
 [+4%, +6%)  ████████                        3
 [+6%, +8%)  ██████████████████████████████  11
[+8%, +10%)  ████████████████                6

insert_reused_count:

  • Average change: +1.0
  • Average regression: +1.0
  • Median change: +1
  • Median regression: +1
  • Standard deviation: 0.0
  • Standard deviation of regressions: 0.0
  • Range: +1 to +1
  • Range of regressions: +1 to +1
  • Queries changed: 6
  • Queries regressed: 6

insert_reused_count % change distribution (6 queries, bin = 2%):

       Range                                  n
------------  ------------------------------  ---
[+12%, +14%)  ██████████████████████████████  2
[+14%, +16%)                                  0
[+16%, +18%)                                  0
[+18%, +20%)                                  0
[+20%, +22%)  ███████████████                 1
[+22%, +24%)                                  0
[+24%, +26%)                                  0
[+26%, +28%)                                  0
[+28%, +30%)                                  0
[+30%, +32%)                                  0
[+32%, +34%)  ███████████████                 1
[+34%, +36%)                                  0
[+36%, +38%)                                  0
[+38%, +40%)                                  0
[+40%, +42%)                                  0
[+42%, +44%)                                  0
[+44%, +46%)                                  0
[+46%, +48%)                                  0
[+48%, +50%)                                  0
[+50%, +52%)  ██████████████████████████████  2

Significant Regressions (Only Metrics Changed)

There were 2 outliers detected. Outlier queries have a significant regression in at least one field. Statistically, this represents either an increase of more than two standard deviations above the mean or a large absolute increase (e.g., 100).

  • yaml-tests/src/test/resources/join-with-order-by-tests.metrics.yaml:599: EXPLAIN select (t1.*), (t3.*) from t1, t3 where t1.a1 IN (1, 2) and t3.aRef = t1.id order by t1.a1 asc, t1.a2 desc
    • explain: [IN arrayDistinct(promote(@c21 AS ARRAY(LONG))) SORTED] | INJOIN q0 -> { COVERING(t1$a1_a2 [EQUALS q0] REVERSE -> [a1: KEY:[0], a2: KEY:[1], id: KEY:[2]]) } | FETCH | FLATMAP q1 -> { ISCAN(t3$aRef [EQUALS q1.id]) AS q2 RETURN ((q1.id AS id, q1.a1 AS a1, q1.a2 AS a2, q1.a3 AS a3) AS t1, (q2.id AS id, q2.c1 AS c1, q2.c2 AS c2, q2.c3 AS c3, q2.aRef AS aRef) AS t3) }
    • task_count: 3113 -> 3206 (+93)
    • transform_count: 1140 -> 1153 (+13)
    • transform_yield_count: 230 -> 233 (+3)
    • insert_new_count: 382 -> 391 (+9)
  • yaml-tests/src/test/resources/join-with-order-by-tests.metrics.yaml:615: EXPLAIN select (t1.*), (t3.*) from t1, t3 where t1.a1 IN (1, 2) and t3.aRef = t1.id order by t1.a1 desc, t1.a2 asc
    • explain: [IN arrayDistinct(promote(@c21 AS ARRAY(LONG))) SORTED DESC] | INJOIN q0 -> { COVERING(t1$a1_a2 [EQUALS q0] -> [a1: KEY:[0], a2: KEY:[1], id: KEY:[2]]) } | FETCH | FLATMAP q1 -> { ISCAN(t3$aRef [EQUALS q1.id]) AS q2 RETURN ((q1.id AS id, q1.a1 AS a1, q1.a2 AS a2, q1.a3 AS a3) AS t1, (q2.id AS id, q2.c1 AS c1, q2.c2 AS c2, q2.c3 AS c3, q2.aRef AS aRef) AS t3) }
    • task_count: 3113 -> 3206 (+93)
    • transform_count: 1140 -> 1153 (+13)
    • transform_yield_count: 230 -> 233 (+3)
    • insert_new_count: 382 -> 391 (+9)

Minor Changes (Only Metrics Changed)

In addition, there were 32 queries with minor changes.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant