From c3c7d7074b1d664d18af15b784941f64c7751a0b Mon Sep 17 00:00:00 2001 From: Radu Berinde Date: Tue, 2 Mar 2021 11:53:18 -0500 Subject: [PATCH] sql: add estimated row count to all operators in EXPLAIN This change adds the estimated row count to all operators in the vanilla EXPLAIN, as long as the tables involved had statistics. Fixes #61310. Release justification: bug fixes and low-risk updates to new functionality Release note (sql change): EXPLAIN now shows estimated row counts for all operators even without VERBOSE (except when we don't have statistics for the tables). --- .../testdata/logic_test/partitioning_implicit | 2 ++ .../testdata/logic_test/regional_by_row | 5 ++++ .../testdata/logic_test/explain_analyze_plans | 2 ++ .../testdata/logic_test/vectorize_threshold | 5 ++++ .../opt/exec/execbuilder/testdata/distsql_agg | 3 ++ .../exec/execbuilder/testdata/distsql_union | 1 + pkg/sql/opt/exec/execbuilder/testdata/explain | 1 + pkg/sql/opt/exec/execbuilder/testdata/fk | 24 +++++++++++++++ pkg/sql/opt/exec/execbuilder/testdata/insert | 11 +++++++ pkg/sql/opt/exec/execbuilder/testdata/limit | 9 ++++++ .../opt/exec/execbuilder/testdata/lookup_join | 20 +++++++++++++ pkg/sql/opt/exec/execbuilder/testdata/orderby | 3 ++ pkg/sql/opt/exec/execbuilder/testdata/spool | 6 ++++ pkg/sql/opt/exec/execbuilder/testdata/srfs | 7 +++++ .../opt/exec/execbuilder/testdata/subquery | 1 + pkg/sql/opt/exec/execbuilder/testdata/unique | 30 +++++++++++++++++++ pkg/sql/opt/exec/explain/emit.go | 13 ++++---- pkg/sql/testdata/explain_tree | 4 ++- 18 files changed, 138 insertions(+), 9 deletions(-) diff --git a/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit b/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit index bb54d159f253..6d77ed7c0843 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit +++ b/pkg/ccl/logictestccl/testdata/logic_test/partitioning_implicit @@ -656,6 +656,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • scan buffer +│ estimated row count: 1 │ label: buffer 1 │ └── • constraint-check @@ -673,6 +674,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 1 label: buffer 1 statement ok diff --git a/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row b/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row index 80daa2cfc2d3..396500cf0d89 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row +++ b/pkg/ccl/logictestccl/testdata/logic_test/regional_by_row @@ -687,6 +687,7 @@ vectorized: true │ │ pred: column15 != crdb_region │ │ │ └── • cross join +│ │ estimated row count: 3 │ │ │ ├── • values │ │ size: 1 column, 3 rows @@ -705,6 +706,7 @@ vectorized: true │ │ pred: (column1 != pk) OR (column15 != crdb_region) │ │ │ └── • cross join +│ │ estimated row count: 3 │ │ │ ├── • values │ │ size: 1 column, 3 rows @@ -723,6 +725,7 @@ vectorized: true │ pred: (column1 != pk) OR (column15 != crdb_region) │ └── • cross join + │ estimated row count: 3 │ ├── • values │ size: 1 column, 3 rows @@ -831,6 +834,7 @@ vectorized: true │ │ locking strength: for update │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 5 columns, 2 rows @@ -1156,6 +1160,7 @@ vectorized: true │ pred: (column1 != pk) OR (column10 != crdb_region_col) │ └── • cross join + │ estimated row count: 3 │ ├── • values │ size: 1 column, 3 rows diff --git a/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans b/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans index 51a0434c5572..90d2cb84b627 100644 --- a/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans +++ b/pkg/sql/logictest/testdata/logic_test/explain_analyze_plans @@ -208,6 +208,7 @@ distribution: full vectorized: true · • group (scalar) +│ estimated row count: 1 │ └── • norows · @@ -330,6 +331,7 @@ network usage: └── • filter │ cluster nodes: │ actual row count: 1 + │ estimated row count: 1 │ filter: column2 IS NOT NULL │ └── • scan buffer diff --git a/pkg/sql/logictest/testdata/logic_test/vectorize_threshold b/pkg/sql/logictest/testdata/logic_test/vectorize_threshold index cc78b334831b..d9f686003f55 100644 --- a/pkg/sql/logictest/testdata/logic_test/vectorize_threshold +++ b/pkg/sql/logictest/testdata/logic_test/vectorize_threshold @@ -66,6 +66,7 @@ distribution: full vectorized: false · • group (scalar) +│ estimated row count: 1 │ └── • scan estimated row count: 100 (100% of the table) @@ -84,6 +85,7 @@ distribution: full vectorized: true · • group (scalar) +│ estimated row count: 1 │ └── • scan estimated row count: 100 (100% of the table) @@ -114,6 +116,7 @@ distribution: full vectorized: true · • group (scalar) +│ estimated row count: 1 │ └── • scan estimated row count: 100,000 (100% of the table) @@ -132,6 +135,7 @@ distribution: full vectorized: false · • group (scalar) +│ estimated row count: 1 │ └── • scan estimated row count: 100,000 (100% of the table) @@ -150,6 +154,7 @@ distribution: full vectorized: true · • merge join +│ estimated row count: 100 │ equality: (a) = (a) │ left cols are key │ right cols are key diff --git a/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg b/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg index 2e346096b9cc..ae4aa4e6346b 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg +++ b/pkg/sql/opt/exec/execbuilder/testdata/distsql_agg @@ -666,8 +666,10 @@ distribution: full vectorized: true · • group (scalar) +│ estimated row count: 1 │ └── • filter + │ estimated row count: 1 │ filter: column2 > 3 │ └── • values @@ -682,6 +684,7 @@ distribution: full vectorized: true · • hash join +│ estimated row count: 2 │ equality: (column1) = (column1) │ ├── • values diff --git a/pkg/sql/opt/exec/execbuilder/testdata/distsql_union b/pkg/sql/opt/exec/execbuilder/testdata/distsql_union index 4094546df965..f5642e8e8e94 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/distsql_union +++ b/pkg/sql/opt/exec/execbuilder/testdata/distsql_union @@ -237,6 +237,7 @@ distribution: full vectorized: true · • union +│ estimated row count: 4 │ ├── • values │ size: 1 column, 2 rows diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain b/pkg/sql/opt/exec/execbuilder/testdata/explain index ff20dd765c27..adac0026e751 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain @@ -1310,6 +1310,7 @@ distribution: local vectorized: true · • group (scalar) +│ estimated row count: 1 │ └── • values size: 2 columns, 2 rows diff --git a/pkg/sql/opt/exec/execbuilder/testdata/fk b/pkg/sql/opt/exec/execbuilder/testdata/fk index 097c75d38238..f764c9e1cb49 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/fk +++ b/pkg/sql/opt/exec/execbuilder/testdata/fk @@ -112,6 +112,7 @@ vectorized: true │ equality cols are key │ └── • filter + │ estimated row count: 1 │ filter: column2 IS NOT NULL │ └── • scan buffer @@ -156,6 +157,7 @@ vectorized: true │ equality cols are key │ └── • filter + │ estimated row count: 1 │ filter: (column2 IS NOT NULL) AND (column3 IS NOT NULL) │ └── • scan buffer @@ -204,6 +206,7 @@ vectorized: true │ │ equality cols are key │ │ │ └── • filter +│ │ estimated row count: 1 │ │ filter: column2 IS NOT NULL │ │ │ └── • scan buffer @@ -219,6 +222,7 @@ vectorized: true │ equality cols are key │ └── • filter + │ estimated row count: 1 │ filter: (column3 IS NOT NULL) AND (column4 IS NOT NULL) │ └── • scan buffer @@ -1210,6 +1214,7 @@ vectorized: true └── • error if rows │ └── • hash join (anti) + │ estimated row count: 2 │ equality: (column2) = (p) │ right cols are key │ @@ -1237,6 +1242,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 1 │ │ │ └── • scan │ estimated row count: 1 (100% of the table) @@ -1249,10 +1255,12 @@ vectorized: true └── • error if rows │ └── • hash join (anti) + │ estimated row count: 0 │ equality: (p_new) = (p) │ right cols are key │ ├── • filter + │ │ estimated row count: 1 │ │ filter: p_new IS NOT NULL │ │ │ └── • scan buffer @@ -1279,6 +1287,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 1 │ │ │ └── • scan │ estimated row count: 1 (100% of the table) @@ -1291,10 +1300,12 @@ vectorized: true └── • error if rows │ └── • hash join (semi) + │ estimated row count: 0 │ equality: (p) = (p) │ left cols are key │ ├── • except + │ │ estimated row count: 1 │ │ │ ├── • scan buffer │ │ label: buffer 1 @@ -1331,10 +1342,12 @@ vectorized: true └── • error if rows │ └── • hash join (semi) + │ estimated row count: 0 │ equality: (p) = (p) │ left cols are key │ ├── • scan buffer + │ estimated row count: 1 │ label: buffer 1 │ └── • scan @@ -1374,6 +1387,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 1 │ │ │ └── • scan │ estimated row count: 1 (100% of the table) @@ -1386,11 +1400,13 @@ vectorized: true └── • error if rows │ └── • lookup join (anti) + │ estimated row count: 0 │ table: p@primary │ equality: (p_new) = (p) │ equality cols are key │ └── • filter + │ estimated row count: 1 │ filter: p_new IS NOT NULL │ └── • scan buffer @@ -1412,6 +1428,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 1 │ │ │ └── • scan │ estimated row count: 1 (100% of the table) @@ -1424,10 +1441,12 @@ vectorized: true └── • error if rows │ └── • lookup join (semi) + │ estimated row count: 0 │ table: c@c_p_idx │ equality: (p) = (p) │ └── • except + │ estimated row count: 1 │ ├── • scan buffer │ label: buffer 1 @@ -1459,10 +1478,12 @@ vectorized: true └── • error if rows │ └── • lookup join (semi) + │ estimated row count: 0 │ table: c@c_p_idx │ equality: (p) = (p) │ └── • scan buffer + estimated row count: 1 label: buffer 1 statement ok @@ -1500,8 +1521,10 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 10 │ │ │ └── • project set +│ │ estimated row count: 10 │ │ │ └── • emptyrow │ @@ -1510,6 +1533,7 @@ vectorized: true └── • error if rows │ └── • hash join (anti) + │ estimated row count: 0 │ equality: (?column?) = (p) │ right cols are key │ diff --git a/pkg/sql/opt/exec/execbuilder/testdata/insert b/pkg/sql/opt/exec/execbuilder/testdata/insert index d70add4e75c3..2571a1bb5ce7 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/insert +++ b/pkg/sql/opt/exec/execbuilder/testdata/insert @@ -377,8 +377,10 @@ vectorized: true │ auto commit │ └── • render + │ estimated row count: 1 │ └── • limit + │ estimated row count: 1 │ count: 1 │ └── • values @@ -395,11 +397,14 @@ vectorized: true │ auto commit │ └── • render + │ estimated row count: 1 │ └── • limit + │ estimated row count: 1 │ count: 1 │ └── • sort + │ estimated row count: 2 │ order: +column2 │ └── • values @@ -416,11 +421,14 @@ vectorized: true │ auto commit │ └── • render + │ estimated row count: 1 │ └── • limit + │ estimated row count: 1 │ count: 1 │ └── • sort + │ estimated row count: 2 │ order: +column2 │ └── • values @@ -437,11 +445,14 @@ vectorized: true │ auto commit │ └── • render + │ estimated row count: 1 │ └── • limit + │ estimated row count: 1 │ count: 1 │ └── • sort + │ estimated row count: 2 │ order: +column2 │ └── • values diff --git a/pkg/sql/opt/exec/execbuilder/testdata/limit b/pkg/sql/opt/exec/execbuilder/testdata/limit index 5e7c40a7d961..7730105c26ab 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/limit +++ b/pkg/sql/opt/exec/execbuilder/testdata/limit @@ -408,24 +408,33 @@ distribution: local vectorized: true · • limit +│ estimated row count: 5 │ count: 5 │ └── • sort + │ estimated row count: 40 │ order: +date_should_be_completed │ └── • union + │ estimated row count: 40 │ ├── • union + │ │ estimated row count: 35 │ │ │ ├── • union + │ │ │ estimated row count: 30 │ │ │ │ │ ├── • union + │ │ │ │ estimated row count: 25 │ │ │ │ │ │ │ ├── • union + │ │ │ │ │ estimated row count: 20 │ │ │ │ │ │ │ │ │ ├── • union + │ │ │ │ │ │ estimated row count: 15 │ │ │ │ │ │ │ │ │ │ │ ├── • union + │ │ │ │ │ │ │ estimated row count: 10 │ │ │ │ │ │ │ │ │ │ │ │ │ ├── • scan │ │ │ │ │ │ │ estimated row count: 5 (0.05% of the table) diff --git a/pkg/sql/opt/exec/execbuilder/testdata/lookup_join b/pkg/sql/opt/exec/execbuilder/testdata/lookup_join index a9842729873e..6be65704bac5 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/lookup_join +++ b/pkg/sql/opt/exec/execbuilder/testdata/lookup_join @@ -222,12 +222,14 @@ distribution: full vectorized: true · • lookup join +│ estimated row count: 0 │ table: data@primary │ equality: (a, b, c, d) = (a,b,c,d) │ equality cols are key │ pred: c > 0 │ └── • filter + │ estimated row count: 10 │ filter: c = 1 │ └── • scan @@ -359,14 +361,17 @@ distribution: full vectorized: true · • distinct +│ estimated row count: 96 │ distinct on: name │ └── • lookup join + │ estimated row count: 323 │ table: books2@primary │ equality: (book) = (title) │ pred: shelf != shelf │ └── • hash join + │ estimated row count: 99 │ equality: (title) = (book) │ ├── • scan @@ -446,6 +451,7 @@ vectorized: true │ equality cols are key │ └── • render + │ estimated row count: 100 │ └── • scan estimated row count: 100 (100% of the table) @@ -608,6 +614,7 @@ distribution: full vectorized: true · • lookup join (left outer) +│ estimated row count: 100 │ table: large@primary │ equality: (a) = (a) │ pred: (b % 6) = 0 @@ -1113,6 +1120,7 @@ distribution: full vectorized: true · • lookup join (semi) +│ estimated row count: 100 │ table: data@primary │ equality: (a) = (a) │ @@ -1131,11 +1139,13 @@ distribution: full vectorized: true · • lookup join (semi) +│ estimated row count: 11 │ table: data@primary │ equality: (a) = (a) │ pred: (b + c) > 15 │ └── • filter + │ estimated row count: 33 │ filter: (a + b) < 20 │ └── • scan @@ -1700,26 +1710,32 @@ distribution: full vectorized: true · • limit +│ estimated row count: 0 │ count: 100 │ └── • sort + │ estimated row count: 0 │ order: -count_rows,+s_name │ └── • group + │ estimated row count: 0 │ group by: s_name │ └── • lookup join (semi) + │ estimated row count: 0 │ table: lineitem@primary │ equality: (l_orderkey) = (l_orderkey) │ pred: l_suppkey != l_suppkey │ └── • lookup join + │ estimated row count: 0 │ table: orders@primary │ equality: (l_orderkey) = (o_orderkey) │ equality cols are key │ pred: o_orderstatus = 'F' │ └── • lookup join (anti) + │ estimated row count: 0 │ table: lineitem@primary │ equality: (l_orderkey) = (l_orderkey) │ pred: l_receiptdate > l_commitdate @@ -1731,19 +1747,23 @@ vectorized: true │ pred: l_receiptdate > l_commitdate │ └── • lookup join + │ estimated row count: 240,049 │ table: lineitem@l_sk │ equality: (s_suppkey) = (l_suppkey) │ └── • lookup join + │ estimated row count: 400 │ table: supplier@primary │ equality: (s_suppkey) = (s_suppkey) │ equality cols are key │ └── • lookup join + │ estimated row count: 400 │ table: supplier@s_nk │ equality: (n_nationkey) = (s_nationkey) │ └── • filter + │ estimated row count: 1 │ filter: n_name = 'SAUDI ARABIA' │ └── • scan diff --git a/pkg/sql/opt/exec/execbuilder/testdata/orderby b/pkg/sql/opt/exec/execbuilder/testdata/orderby index 4dd899ebb3d8..5f3334d35958 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/orderby +++ b/pkg/sql/opt/exec/execbuilder/testdata/orderby @@ -653,6 +653,7 @@ distribution: local vectorized: true · • ordinality +│ estimated row count: 3 │ └── • values size: 1 column, 3 rows @@ -664,9 +665,11 @@ distribution: local vectorized: true · • sort +│ estimated row count: 3 │ order: -"ordinality" │ └── • ordinality + │ estimated row count: 3 │ └── • values size: 1 column, 3 rows diff --git a/pkg/sql/opt/exec/execbuilder/testdata/spool b/pkg/sql/opt/exec/execbuilder/testdata/spool index b1286cb0b4da..10d13a29e583 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/spool +++ b/pkg/sql/opt/exec/execbuilder/testdata/spool @@ -115,9 +115,11 @@ vectorized: true • root │ ├── • limit +│ │ estimated row count: 1 │ │ count: 1 │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 (a) │ └── • subquery @@ -129,6 +131,7 @@ vectorized: true │ label: buffer 1 (a) │ └── • upsert + │ estimated row count: 2 │ into: t(x) │ └── • values @@ -238,9 +241,11 @@ vectorized: true • root │ ├── • limit +│ │ estimated row count: 1 │ │ count: 1 │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ └── • subquery @@ -252,6 +257,7 @@ vectorized: true │ label: buffer 1 │ └── • upsert + │ estimated row count: 2 │ into: t(x) │ └── • values diff --git a/pkg/sql/opt/exec/execbuilder/testdata/srfs b/pkg/sql/opt/exec/execbuilder/testdata/srfs index 664fa6107554..8b9dce2cf0fc 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/srfs +++ b/pkg/sql/opt/exec/execbuilder/testdata/srfs @@ -9,6 +9,7 @@ distribution: local vectorized: true · • project set +│ estimated row count: 10 │ └── • emptyrow @@ -19,12 +20,15 @@ distribution: local vectorized: true · • cross join +│ estimated row count: 100 │ ├── • project set +│ │ estimated row count: 10 │ │ │ └── • emptyrow │ └── • project set + │ estimated row count: 10 │ └── • emptyrow @@ -35,6 +39,7 @@ distribution: local vectorized: true · • project set +│ estimated row count: 1 │ └── • emptyrow @@ -45,6 +50,7 @@ distribution: local vectorized: true · • project set +│ estimated row count: 10 │ └── • emptyrow @@ -58,6 +64,7 @@ distribution: local vectorized: true · • project set +│ estimated row count: 10 │ └── • emptyrow diff --git a/pkg/sql/opt/exec/execbuilder/testdata/subquery b/pkg/sql/opt/exec/execbuilder/testdata/subquery index 603ab0042289..9a6fe842a6f3 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/subquery +++ b/pkg/sql/opt/exec/execbuilder/testdata/subquery @@ -163,6 +163,7 @@ distribution: local vectorized: true · • sort +│ estimated row count: 3 │ order: +foo1 │ └── • values diff --git a/pkg/sql/opt/exec/execbuilder/testdata/unique b/pkg/sql/opt/exec/execbuilder/testdata/unique index 76e5fb45dfaa..b9ef58766286 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/unique +++ b/pkg/sql/opt/exec/execbuilder/testdata/unique @@ -271,6 +271,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ └── • constraint-check @@ -287,6 +288,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 2 label: buffer 1 # No need to plan checks for w since it's always null. @@ -322,6 +324,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 2 label: buffer 1 # Use all the unique indexes and constraints as arbiters for DO NOTHING with no @@ -475,6 +478,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ ├── • constraint-check @@ -487,6 +491,7 @@ vectorized: true │ │ pred: column2 != b │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ └── • constraint-check @@ -503,6 +508,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 2 label: buffer 1 # Insert with non-constant input. @@ -592,6 +598,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -610,6 +617,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ └── • constraint-check @@ -626,6 +634,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 2 label: buffer 1 # Combine unique checks with foreign keys. There should be two foreign key @@ -645,6 +654,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -663,6 +673,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ ├── • constraint-check @@ -986,9 +997,11 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • filter +│ │ estimated row count: 1 │ │ filter: column3 > 0 │ │ │ └── • scan buffer +│ estimated row count: 2 │ label: buffer 1 │ └── • constraint-check @@ -1008,9 +1021,11 @@ vectorized: true │ spans: FULL SCAN │ └── • filter + │ estimated row count: 1 │ filter: column3 > 0 │ └── • scan buffer + estimated row count: 2 label: buffer 1 # No need to plan checks for a since it's always null. @@ -1048,9 +1063,11 @@ vectorized: true │ spans: FULL SCAN │ └── • filter + │ estimated row count: 1 │ filter: column3 > 0 │ └── • scan buffer + estimated row count: 2 label: buffer 1 # Use all the unique indexes and constraints as arbiters for DO NOTHING with no @@ -1441,6 +1458,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -1459,6 +1477,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 2 label: buffer 1 # By default, we do not require checks on UUID columns set to gen_random_uuid(), @@ -1495,6 +1514,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 1 label: buffer 1 # The default value of id1 is gen_random_uuid(), so we don't need to plan checks @@ -1532,6 +1552,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 1 label: buffer 1 # We can also detect gen_random_uuid() when it is a projection. @@ -1608,6 +1629,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • scan buffer +│ estimated row count: 1 │ label: buffer 1 │ └── • constraint-check @@ -1625,6 +1647,7 @@ vectorized: true │ spans: FULL SCAN │ └── • scan buffer + estimated row count: 1 label: buffer 1 statement ok @@ -2710,6 +2733,7 @@ vectorized: true │ │ locking strength: for update │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -2772,6 +2796,7 @@ vectorized: true │ │ locking strength: for update │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -2835,6 +2860,7 @@ vectorized: true │ │ locking strength: for update │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 2 columns, 2 rows @@ -2971,6 +2997,7 @@ vectorized: true │ │ spans: FULL SCAN │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -3160,11 +3187,13 @@ vectorized: true │ │ equality cols are key │ │ │ └── • distinct +│ │ estimated row count: 2 │ │ distinct on: column10 │ │ nulls are distinct │ │ error on duplicate │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows @@ -3242,6 +3271,7 @@ vectorized: true │ │ label: buffer 1 │ │ │ └── • render +│ │ estimated row count: 2 │ │ │ └── • values │ size: 3 columns, 2 rows diff --git a/pkg/sql/opt/exec/explain/emit.go b/pkg/sql/opt/exec/explain/emit.go index 5c988ac758f9..ebb7a0528927 100644 --- a/pkg/sql/opt/exec/explain/emit.go +++ b/pkg/sql/opt/exec/explain/emit.go @@ -348,11 +348,8 @@ func (e *emitter) emitNodeAttributes(n *Node) error { if stats, ok := n.annotations[exec.EstimatedStatsID]; ok { s := stats.(*exec.EstimatedStats) - // In verbose mode, we show the estimated row count for all nodes (except - // Values, where it is redundant). In non-verbose mode, we only show it for - // scans (and when it is based on real statistics), where it is most useful - // and accurate. - if n.op != valuesOp && (e.ob.flags.Verbose || n.op == scanOp) { + // Show the estimated row count (except Values, where it is redundant). + if n.op != valuesOp { count := uint64(math.Round(s.RowCount)) if s.TableStatsAvailable { if n.op == scanOp && s.TableRowCount != 0 { @@ -381,10 +378,10 @@ func (e *emitter) emitNodeAttributes(n *Node) error { // No stats available. if e.ob.flags.Verbose { e.ob.Attrf("estimated row count", "%s (missing stats)", humanizeutil.Count(count)) - } else { + } else if n.op == scanOp { // In non-verbose mode, don't show the row count (which is not based - // on reality); only show a "missing stats" field. Don't show it for - // virtual tables though, where we expect no stats. + // on reality); only show a "missing stats" field for scans. Don't + // show it for virtual tables though, where we expect no stats. if !n.args.(*scanArgs).Table.IsVirtualTable() { e.ob.AddField("missing stats", "") } diff --git a/pkg/sql/testdata/explain_tree b/pkg/sql/testdata/explain_tree index 651018949ae9..253040f233ac 100644 --- a/pkg/sql/testdata/explain_tree +++ b/pkg/sql/testdata/explain_tree @@ -346,7 +346,9 @@ children: value: one row children: - name: max1row - attrs: [] + attrs: + - key: estimated row count + value: "1" children: - name: filter attrs: