Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sql: fix recent regression in EXPLAIN ANALYZE #143088

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions pkg/sql/distsql_physical_planner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}

Expand Down
25 changes: 24 additions & 1 deletion pkg/sql/instrumentation.go
Original file line number Diff line number Diff line change
Expand Up @@ -959,11 +959,34 @@ 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 len(oldComponents) != len(components) {
continue
}
dup := true
for i := range oldComponents {
// Duplicate association can only happen when component IDs are
// in exactly the same order.
if oldComponents[i] != components[i] {
dup = false
break
}
}
if dup {
// 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}
Expand Down
99 changes: 99 additions & 0 deletions pkg/sql/opt/exec/execbuilder/testdata/explain_analyze
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,102 @@ 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

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)
│ │
│ ├── • 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
│ │
│ └── • 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']
Loading