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']