diff --git a/pkg/backup/backup_compaction_test.go b/pkg/backup/backup_compaction_test.go index 8e1bc418f39..ae3509dfe98 100644 --- a/pkg/backup/backup_compaction_test.go +++ b/pkg/backup/backup_compaction_test.go @@ -428,6 +428,8 @@ func TestScheduledBackupCompaction(t *testing.T) { defer leaktest.AfterTest(t)() defer log.Scope(t).Close(t) + skip.WithIssue(t, 143394, "flaky test") + ctx := context.Background() th, cleanup := newTestHelper(t) defer cleanup() diff --git a/pkg/sql/distsql_physical_planner.go b/pkg/sql/distsql_physical_planner.go index 6f31bc3eb2d..9faf65df28c 100644 --- a/pkg/sql/distsql_physical_planner.go +++ b/pkg/sql/distsql_physical_planner.go @@ -1066,8 +1066,9 @@ func (p *PlanningCtx) setUpForMainQuery( } // associateWithPlanNode returns a callback function (possibly nil) that should -// be invoked when a new stage of processors is added that corresponds to the -// given planNode. +// be invoked to associate the last stage of processors with the given planNode. +// The returned function can be safely invoked multiple times for the given +// planNode and the same last stage of processors. func (p *PlanningCtx) associateWithPlanNode(node planNode) func(*physicalplan.PhysicalPlan) { if p.associateNodeWithComponents == nil { return nil @@ -4227,6 +4228,19 @@ func (dsp *DistSQLPlanner) createPhysPlanForPlanNode( return nil, err } + if associateWithPlanNode := planCtx.associateWithPlanNode(node); associateWithPlanNode != nil { + // Even though we might not have created a new stage in the physical + // plan for the current planNode, we still need to associate it with the + // last stage. This is needed to handle cases where a single physical + // plan stage handles multiple planNodes (e.g. renderNode that is done + // by adjusting PostProcessSpec). + // + // Note that it is ok if we already did the association with the current + // planNode when created the last stage of the physical plan - the + // callback handles this case safely (i.e. without double-counting). + associateWithPlanNode(&plan.PhysicalPlan) + } + return plan, err } diff --git a/pkg/sql/instrumentation.go b/pkg/sql/instrumentation.go index 5c739fbb563..1b1a5d9b753 100644 --- a/pkg/sql/instrumentation.go +++ b/pkg/sql/instrumentation.go @@ -9,6 +9,7 @@ import ( "bytes" "context" "fmt" + "slices" "time" "github.com/cockroachdb/cockroach/pkg/keys" @@ -959,11 +960,22 @@ type execNodeTraceMetadata map[exec.Node][]execComponents type execComponents []execinfrapb.ComponentID // associateNodeWithComponents is called during planning, as processors are -// planned for an execution operator. +// planned for an execution operator. This function can be called multiple times +// for the same exec.Node and execComponents. func (m execNodeTraceMetadata) associateNodeWithComponents( node exec.Node, components execComponents, ) { if prevComponents, ok := m[node]; ok { + // We already have some components associated with this node. Check + // whether this is a duplicate association (that should be a no-op). + for _, oldComponents := range prevComponents { + if slices.Equal(oldComponents, components) { + // This association has already been performed. + return + } + } + // This must be a new stage in the physical plan, so we want to extend + // the mapping for the exec.Node. m[node] = append(prevComponents, components) } else { m[node] = []execComponents{components} diff --git a/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze b/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze index 1586d25d7a2..2ce139b70c7 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze +++ b/pkg/sql/opt/exec/execbuilder/testdata/explain_analyze @@ -82,3 +82,112 @@ vectorized: true estimated row count: 10 (missing stats) table: privileges@privileges_path_user_id_key spans: /"vtable/crdb_internal/tables"-/"vtable/crdb_internal/tables"/PrefixEnd + +# Regression test for not showing the execution statistics that correspond to +# scans of the virtual tables. +query T +EXPLAIN ANALYZE SHOW TABLES; +---- +planning time: 10µs +execution time: 100µs +distribution: <hidden> +vectorized: <hidden> +plan type: custom +maximum memory usage: <hidden> +network usage: <hidden> +regions: <hidden> +isolation level: serializable +priority: normal +quality of service: regular +· +• sort +│ sql nodes: <hidden> +│ regions: <hidden> +│ actual row count: 1 +│ estimated max memory allocated: 0 B +│ order: +nspname,+relname +│ +└── • render + │ + └── • hash join (left outer) + │ sql nodes: <hidden> + │ regions: <hidden> + │ actual row count: 1 + │ estimated max memory allocated: 0 B + │ equality: (column80) = (table_id) + │ + ├── • render + │ │ + │ └── • hash join (left outer) + │ │ sql nodes: <hidden> + │ │ regions: <hidden> + │ │ actual row count: 1 + │ │ estimated max memory allocated: 0 B + │ │ equality: (column62) = (table_id) + │ │ right cols are key + │ │ + │ ├── • render + │ │ │ + │ │ └── • hash join (right outer) + │ │ │ sql nodes: <hidden> + │ │ │ regions: <hidden> + │ │ │ actual row count: 1 + │ │ │ estimated max memory allocated: 0 B + │ │ │ equality: (oid) = (relowner) + │ │ │ + │ │ ├── • virtual table + │ │ │ sql nodes: <hidden> + │ │ │ regions: <hidden> + │ │ │ actual row count: 4 + │ │ │ table: pg_roles@primary + │ │ │ + │ │ └── • hash join + │ │ │ sql nodes: <hidden> + │ │ │ regions: <hidden> + │ │ │ actual row count: 1 + │ │ │ estimated max memory allocated: 0 B + │ │ │ equality: (oid) = (relnamespace) + │ │ │ + │ │ ├── • filter + │ │ │ │ sql nodes: <hidden> + │ │ │ │ regions: <hidden> + │ │ │ │ actual row count: 1 + │ │ │ │ filter: nspname NOT IN ('crdb_internal', 'information_schema', __more1_10__, 'pg_extension') + │ │ │ │ + │ │ │ └── • virtual table + │ │ │ sql nodes: <hidden> + │ │ │ regions: <hidden> + │ │ │ actual row count: 5 + │ │ │ table: pg_namespace@primary + │ │ │ + │ │ └── • filter + │ │ │ sql nodes: <hidden> + │ │ │ regions: <hidden> + │ │ │ actual row count: 330 + │ │ │ filter: relkind IN ('S', 'm', __more1_10__, 'v') + │ │ │ + │ │ └── • virtual table + │ │ sql nodes: <hidden> + │ │ regions: <hidden> + │ │ actual row count: 362 + │ │ table: pg_class@primary + │ │ + │ └── • distinct + │ │ sql nodes: <hidden> + │ │ regions: <hidden> + │ │ actual row count: 330 + │ │ estimated max memory allocated: 0 B + │ │ distinct on: table_id + │ │ + │ └── • virtual table + │ sql nodes: <hidden> + │ regions: <hidden> + │ actual row count: 330 + │ table: table_row_statistics@primary + │ + └── • virtual table + sql nodes: <hidden> + regions: <hidden> + actual row count: 1 + table: tables@tables_database_name_idx (partial index) + spans: [/'test' - /'test']