diff --git a/pkg/sql/opt/exec/execbuilder/testdata/partial_index b/pkg/sql/opt/exec/execbuilder/testdata/partial_index index dfd4fbcb9c53..f6171f375fe9 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/partial_index +++ b/pkg/sql/opt/exec/execbuilder/testdata/partial_index @@ -146,3 +146,28 @@ PREPARE q66465_b AS SELECT k FROM t66465@idx WHERE k + i > 0 AND t > now() statement ok EXECUTE q66465_b + +# Regression test for #70116. Partial index validation queries performed during +# a backfill should be efficient. + +statement ok +CREATE TABLE t70116 ( + k INT PRIMARY KEY, + a INT, + b INT, + INDEX a_idx (a) WHERE b > 0 +) + +# This query mimics a partial index validation query. +query T +EXPLAIN SELECT count(1) FROM t70116@a_idx WHERE b > 0 +---- +distribution: local +vectorized: true +· +• group (scalar) +│ +└── • scan + missing stats + table: t70116@a_idx (partial index) + spans: FULL SCAN diff --git a/pkg/sql/opt/xform/rules/groupby.opt b/pkg/sql/opt/xform/rules/groupby.opt index 48283ade18ac..286c8adc4410 100644 --- a/pkg/sql/opt/xform/rules/groupby.opt +++ b/pkg/sql/opt/xform/rules/groupby.opt @@ -275,7 +275,7 @@ # projections instead of using an IndexJoin. The Project can be eliminated for # the same reasons as the IndexJoin. [EliminateIndexJoinOrProjectInsideGroupBy, Explore] -(GroupBy | DistinctOn | EnsureUpsertDistinctOn +(GroupBy | ScalarGroupBy | DistinctOn | EnsureUpsertDistinctOn (IndexJoin | Project $input:*) $aggs:* $private:* & diff --git a/pkg/sql/opt/xform/testdata/external/tpce b/pkg/sql/opt/xform/testdata/external/tpce index e0b4017a6a0f..86720d440c59 100644 --- a/pkg/sql/opt/xform/testdata/external/tpce +++ b/pkg/sql/opt/xform/testdata/external/tpce @@ -2747,26 +2747,18 @@ project │ ├── cardinality: [1 - 1] │ ├── key: () │ ├── fd: ()-->(10) - │ ├── project - │ │ ├── columns: tx_id:1!null tx_rate:3!null - │ │ ├── key: (1) - │ │ ├── fd: (1)-->(3) - │ │ └── project - │ │ ├── columns: tx_id:1!null tx_rate:3!null cx_tx_id:6!null - │ │ ├── key: (6) - │ │ ├── fd: (1)-->(3), (1)==(6), (6)==(1) - │ │ └── inner-join (lookup taxrate) - │ │ ├── columns: tx_id:1!null tx_rate:3!null cx_tx_id:6!null cx_c_id:7!null - │ │ ├── key columns: [6] = [1] - │ │ ├── lookup columns are key - │ │ ├── key: (6) - │ │ ├── fd: ()-->(7), (1)-->(3), (1)==(6), (6)==(1) - │ │ ├── scan customer_taxrate@secondary - │ │ │ ├── columns: cx_tx_id:6!null cx_c_id:7!null - │ │ │ ├── constraint: /7/6: [/0 - /0] - │ │ │ ├── key: (6) - │ │ │ └── fd: ()-->(7) - │ │ └── filters (true) + │ ├── inner-join (lookup taxrate) + │ │ ├── columns: tx_id:1!null tx_rate:3!null cx_tx_id:6!null cx_c_id:7!null + │ │ ├── key columns: [6] = [1] + │ │ ├── lookup columns are key + │ │ ├── key: (6) + │ │ ├── fd: ()-->(7), (1)-->(3), (1)==(6), (6)==(1) + │ │ ├── scan customer_taxrate@secondary + │ │ │ ├── columns: cx_tx_id:6!null cx_c_id:7!null + │ │ │ ├── constraint: /7/6: [/0 - /0] + │ │ │ ├── key: (6) + │ │ │ └── fd: ()-->(7) + │ │ └── filters (true) │ └── aggregations │ └── sum [as=sum:10, outer=(3)] │ └── tx_rate:3 @@ -4003,26 +3995,18 @@ project │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () │ │ │ │ ├── fd: ()-->(44) - │ │ │ │ ├── project - │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null - │ │ │ │ │ ├── key: (35) - │ │ │ │ │ ├── fd: (35)-->(37) - │ │ │ │ │ └── project - │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null cx_tx_id:40!null - │ │ │ │ │ ├── key: (40) - │ │ │ │ │ ├── fd: (35)-->(37), (35)==(40), (40)==(35) - │ │ │ │ │ └── inner-join (lookup taxrate) - │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null cx_tx_id:40!null cx_c_id:41!null - │ │ │ │ │ ├── key columns: [40] = [35] - │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ ├── key: (40) - │ │ │ │ │ ├── fd: ()-->(41), (35)-->(37), (35)==(40), (40)==(35) - │ │ │ │ │ ├── scan customer_taxrate@secondary - │ │ │ │ │ │ ├── columns: cx_tx_id:40!null cx_c_id:41!null - │ │ │ │ │ │ ├── constraint: /41/40: [/0 - /0] - │ │ │ │ │ │ ├── key: (40) - │ │ │ │ │ │ └── fd: ()-->(41) - │ │ │ │ │ └── filters (true) + │ │ │ │ ├── inner-join (lookup taxrate) + │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null cx_tx_id:40!null cx_c_id:41!null + │ │ │ │ │ ├── key columns: [40] = [35] + │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ ├── key: (40) + │ │ │ │ │ ├── fd: ()-->(41), (35)-->(37), (35)==(40), (40)==(35) + │ │ │ │ │ ├── scan customer_taxrate@secondary + │ │ │ │ │ │ ├── columns: cx_tx_id:40!null cx_c_id:41!null + │ │ │ │ │ │ ├── constraint: /41/40: [/0 - /0] + │ │ │ │ │ │ ├── key: (40) + │ │ │ │ │ │ └── fd: ()-->(41) + │ │ │ │ │ └── filters (true) │ │ │ │ └── aggregations │ │ │ │ └── sum [as=sum:44, outer=(37)] │ │ │ │ └── tx_rate:37 diff --git a/pkg/sql/opt/xform/testdata/external/tpce-no-stats b/pkg/sql/opt/xform/testdata/external/tpce-no-stats index ffd07db0119e..d2d667dba54f 100644 --- a/pkg/sql/opt/xform/testdata/external/tpce-no-stats +++ b/pkg/sql/opt/xform/testdata/external/tpce-no-stats @@ -2781,26 +2781,18 @@ project │ ├── cardinality: [1 - 1] │ ├── key: () │ ├── fd: ()-->(10) - │ ├── project - │ │ ├── columns: tx_id:1!null tx_rate:3!null - │ │ ├── key: (1) - │ │ ├── fd: (1)-->(3) - │ │ └── project - │ │ ├── columns: tx_id:1!null tx_rate:3!null cx_tx_id:6!null - │ │ ├── key: (6) - │ │ ├── fd: (1)-->(3), (1)==(6), (6)==(1) - │ │ └── inner-join (lookup taxrate) - │ │ ├── columns: tx_id:1!null tx_rate:3!null cx_tx_id:6!null cx_c_id:7!null - │ │ ├── key columns: [6] = [1] - │ │ ├── lookup columns are key - │ │ ├── key: (6) - │ │ ├── fd: ()-->(7), (1)-->(3), (1)==(6), (6)==(1) - │ │ ├── scan customer_taxrate@secondary - │ │ │ ├── columns: cx_tx_id:6!null cx_c_id:7!null - │ │ │ ├── constraint: /7/6: [/0 - /0] - │ │ │ ├── key: (6) - │ │ │ └── fd: ()-->(7) - │ │ └── filters (true) + │ ├── inner-join (lookup taxrate) + │ │ ├── columns: tx_id:1!null tx_rate:3!null cx_tx_id:6!null cx_c_id:7!null + │ │ ├── key columns: [6] = [1] + │ │ ├── lookup columns are key + │ │ ├── key: (6) + │ │ ├── fd: ()-->(7), (1)-->(3), (1)==(6), (6)==(1) + │ │ ├── scan customer_taxrate@secondary + │ │ │ ├── columns: cx_tx_id:6!null cx_c_id:7!null + │ │ │ ├── constraint: /7/6: [/0 - /0] + │ │ │ ├── key: (6) + │ │ │ └── fd: ()-->(7) + │ │ └── filters (true) │ └── aggregations │ └── sum [as=sum:10, outer=(3)] │ └── tx_rate:3 @@ -4036,26 +4028,18 @@ project │ │ │ │ ├── cardinality: [1 - 1] │ │ │ │ ├── key: () │ │ │ │ ├── fd: ()-->(44) - │ │ │ │ ├── project - │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null - │ │ │ │ │ ├── key: (35) - │ │ │ │ │ ├── fd: (35)-->(37) - │ │ │ │ │ └── project - │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null cx_tx_id:40!null - │ │ │ │ │ ├── key: (40) - │ │ │ │ │ ├── fd: (35)-->(37), (35)==(40), (40)==(35) - │ │ │ │ │ └── inner-join (lookup taxrate) - │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null cx_tx_id:40!null cx_c_id:41!null - │ │ │ │ │ ├── key columns: [40] = [35] - │ │ │ │ │ ├── lookup columns are key - │ │ │ │ │ ├── key: (40) - │ │ │ │ │ ├── fd: ()-->(41), (35)-->(37), (35)==(40), (40)==(35) - │ │ │ │ │ ├── scan customer_taxrate@secondary - │ │ │ │ │ │ ├── columns: cx_tx_id:40!null cx_c_id:41!null - │ │ │ │ │ │ ├── constraint: /41/40: [/0 - /0] - │ │ │ │ │ │ ├── key: (40) - │ │ │ │ │ │ └── fd: ()-->(41) - │ │ │ │ │ └── filters (true) + │ │ │ │ ├── inner-join (lookup taxrate) + │ │ │ │ │ ├── columns: tx_id:35!null tx_rate:37!null cx_tx_id:40!null cx_c_id:41!null + │ │ │ │ │ ├── key columns: [40] = [35] + │ │ │ │ │ ├── lookup columns are key + │ │ │ │ │ ├── key: (40) + │ │ │ │ │ ├── fd: ()-->(41), (35)-->(37), (35)==(40), (40)==(35) + │ │ │ │ │ ├── scan customer_taxrate@secondary + │ │ │ │ │ │ ├── columns: cx_tx_id:40!null cx_c_id:41!null + │ │ │ │ │ │ ├── constraint: /41/40: [/0 - /0] + │ │ │ │ │ │ ├── key: (40) + │ │ │ │ │ │ └── fd: ()-->(41) + │ │ │ │ │ └── filters (true) │ │ │ │ └── aggregations │ │ │ │ └── sum [as=sum:44, outer=(37)] │ │ │ │ └── tx_rate:37 diff --git a/pkg/sql/opt/xform/testdata/rules/groupby b/pkg/sql/opt/xform/testdata/rules/groupby index 0ccc877dbf89..5f1eb2147962 100644 --- a/pkg/sql/opt/xform/testdata/rules/groupby +++ b/pkg/sql/opt/xform/testdata/rules/groupby @@ -2552,6 +2552,22 @@ group-by └── aggregations └── count-rows [as=count_rows:8] +# Rule applies for scalar group-by. +opt expect=EliminateIndexJoinOrProjectInsideGroupBy +SELECT count(1) FROM abcd@partial_ab WHERE c > 0 +---- +scalar-group-by + ├── columns: count:9!null + ├── cardinality: [1 - 1] + ├── key: () + ├── fd: ()-->(9) + ├── scan abcd@partial_ab,partial + │ ├── columns: rowid:5!null + │ ├── flags: force-index=partial_ab + │ └── key: (5) + └── aggregations + └── count-rows [as=count:9] + # Rule applies for distinct-on. opt expect=EliminateIndexJoinOrProjectInsideGroupBy SELECT DISTINCT a, b FROM abcd WHERE c > 0 diff --git a/pkg/sql/opt/xform/testdata/rules/select b/pkg/sql/opt/xform/testdata/rules/select index 3efc46c5adbe..7e41a80a1f2c 100644 --- a/pkg/sql/opt/xform/testdata/rules/select +++ b/pkg/sql/opt/xform/testdata/rules/select @@ -8057,46 +8057,44 @@ scalar-group-by ├── cardinality: [1 - 1] ├── key: () ├── fd: ()-->(7) - ├── project - │ ├── columns: u:2 v:3 - │ └── distinct-on - │ ├── columns: k:1!null u:2 v:3 - │ ├── grouping columns: k:1!null - │ ├── internal-ordering: +1 - │ ├── key: (1) - │ ├── fd: (1)-->(2,3) - │ ├── union-all - │ │ ├── columns: k:1!null u:2 v:3 - │ │ ├── left columns: k:8 u:9 v:10 - │ │ ├── right columns: k:14 u:15 v:16 - │ │ ├── ordering: +1 - │ │ ├── index-join d - │ │ │ ├── columns: k:8!null u:9!null v:10 - │ │ │ ├── key: (8) - │ │ │ ├── fd: ()-->(9), (8)-->(10) - │ │ │ ├── ordering: +8 opt(9) [actual: +8] - │ │ │ └── scan d@u - │ │ │ ├── columns: k:8!null u:9!null - │ │ │ ├── constraint: /9/8: [/1 - /1] - │ │ │ ├── key: (8) - │ │ │ ├── fd: ()-->(9) - │ │ │ └── ordering: +8 opt(9) [actual: +8] - │ │ └── index-join d - │ │ ├── columns: k:14!null u:15 v:16!null - │ │ ├── key: (14) - │ │ ├── fd: ()-->(16), (14)-->(15) - │ │ ├── ordering: +14 opt(16) [actual: +14] - │ │ └── scan d@v - │ │ ├── columns: k:14!null v:16!null - │ │ ├── constraint: /16/14: [/1 - /1] - │ │ ├── key: (14) - │ │ ├── fd: ()-->(16) - │ │ └── ordering: +14 opt(16) [actual: +14] - │ └── aggregations - │ ├── const-agg [as=u:2, outer=(2)] - │ │ └── u:2 - │ └── const-agg [as=v:3, outer=(3)] - │ └── v:3 + ├── distinct-on + │ ├── columns: k:1!null u:2 v:3 + │ ├── grouping columns: k:1!null + │ ├── internal-ordering: +1 + │ ├── key: (1) + │ ├── fd: (1)-->(2,3) + │ ├── union-all + │ │ ├── columns: k:1!null u:2 v:3 + │ │ ├── left columns: k:8 u:9 v:10 + │ │ ├── right columns: k:14 u:15 v:16 + │ │ ├── ordering: +1 + │ │ ├── index-join d + │ │ │ ├── columns: k:8!null u:9!null v:10 + │ │ │ ├── key: (8) + │ │ │ ├── fd: ()-->(9), (8)-->(10) + │ │ │ ├── ordering: +8 opt(9) [actual: +8] + │ │ │ └── scan d@u + │ │ │ ├── columns: k:8!null u:9!null + │ │ │ ├── constraint: /9/8: [/1 - /1] + │ │ │ ├── key: (8) + │ │ │ ├── fd: ()-->(9) + │ │ │ └── ordering: +8 opt(9) [actual: +8] + │ │ └── index-join d + │ │ ├── columns: k:14!null u:15 v:16!null + │ │ ├── key: (14) + │ │ ├── fd: ()-->(16), (14)-->(15) + │ │ ├── ordering: +14 opt(16) [actual: +14] + │ │ └── scan d@v + │ │ ├── columns: k:14!null v:16!null + │ │ ├── constraint: /16/14: [/1 - /1] + │ │ ├── key: (14) + │ │ ├── fd: ()-->(16) + │ │ └── ordering: +14 opt(16) [actual: +14] + │ └── aggregations + │ ├── const-agg [as=u:2, outer=(2)] + │ │ └── u:2 + │ └── const-agg [as=v:3, outer=(3)] + │ └── v:3 └── aggregations └── count-rows [as=count_rows:7]