Skip to content

Commit 687f008

Browse files
committed
sql: dynamically disable vectorized execution
1 parent ae7600a commit 687f008

File tree

6 files changed

+50
-15
lines changed

6 files changed

+50
-15
lines changed

pkg/sql/distsql_running.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -459,25 +459,29 @@ func (dsp *DistSQLPlanner) setupFlows(
459459
CollectStats: planCtx.collectExecStats,
460460
StatementSQL: statementSQL,
461461
}
462-
if localState.IsLocal {
463-
// VectorizeMode is the only field that the setup code expects to be set
464-
// in the local flows.
465-
setupReq.EvalContext.SessionData.VectorizeMode = evalCtx.SessionData().VectorizeMode
466-
} else {
467-
// In distributed plans populate some extra state.
462+
if !localState.IsLocal {
463+
// In distributed plans populate some extra state. VectorizeMode is the
464+
// only field that the setup code expects to be set in the local flows.
468465
setupReq.EvalContext = execinfrapb.MakeEvalContext(evalCtx)
469466
if jobTag, ok := logtags.FromContext(ctx).GetTag("job"); ok {
470467
setupReq.JobTag = jobTag.ValueStr()
471468
}
472469
}
470+
vectorizeMode := evalCtx.SessionData().VectorizeMode
471+
if planCtx.planner != nil && planCtx.planner.curPlan.avoidVectorization {
472+
// Vectorization has been automatically disabled for this plan.
473+
vectorizeMode = sessiondatapb.VectorizeOff
474+
}
475+
setupReq.EvalContext.SessionData.VectorizeMode = vectorizeMode
476+
// In local and distributed plans set the vectorized mode.
473477
if evalCtx.SessionData().PropagateAdmissionHeaderToLeafTransactions && localState.Txn != nil {
474478
// Propagate the admission control header so that leaf transactions
475479
// correctly inherit it.
476480
setupReq.LeafTxnAdmissionHeader = localState.Txn.AdmissionHeader()
477481
}
478482

479483
var isVectorized bool
480-
if vectorizeMode := evalCtx.SessionData().VectorizeMode; vectorizeMode != sessiondatapb.VectorizeOff {
484+
if vectorizeMode != sessiondatapb.VectorizeOff {
481485
// Now we determine whether the vectorized engine supports the flow
482486
// specs.
483487
isVectorized = true

pkg/sql/explain_plan.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func (e *explainPlanNode) startExec(params runParams) error {
9393

9494
ctxSessionData := planCtx.EvalContext().SessionData()
9595
var willVectorize bool
96-
if ctxSessionData.VectorizeMode == sessiondatapb.VectorizeOff {
96+
if ctxSessionData.VectorizeMode == sessiondatapb.VectorizeOff || params.p.curPlan.avoidVectorization {
9797
willVectorize = false
9898
} else {
9999
willVectorize = true

pkg/sql/opt/memo/cost.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ type Cost struct {
2020
// fullScanCount is the number of full table or index scans in a
2121
// sub-plan, up to 255.
2222
fullScanCount uint8
23+
// maxCardinality is the maximum cardinality in any expression in a
24+
// sub-plan.
25+
maxCardinality uint32
2326
}
2427
}
2528

@@ -63,6 +66,7 @@ func (c *Cost) Add(other Cost) {
6366
} else {
6467
c.aux.fullScanCount += other.aux.fullScanCount
6568
}
69+
c.aux.maxCardinality = max(c.aux.maxCardinality, other.aux.maxCardinality)
6670
}
6771

6872
// FullScanCount returns the number of full scans in the cost.
@@ -79,6 +83,17 @@ func (c *Cost) IncrFullScanCount() {
7983
c.aux.fullScanCount++
8084
}
8185

86+
// MaxCardinality returns the maximum cardinality in the cost.
87+
func (c Cost) MaxCardinality() uint32 {
88+
return c.aux.maxCardinality
89+
}
90+
91+
// RatchetMaxCardinality ratchets the max cardinality in the cost to card. No-op
92+
// if the max cardinality is greater than or equal to card.
93+
func (c *Cost) RatchetMaxCardinality(card uint32) {
94+
c.aux.maxCardinality = max(c.aux.maxCardinality, card)
95+
}
96+
8297
// CostFlags contains flags that penalize the cost of an operator.
8398
type CostFlags struct {
8499
// FullScanPenalty is true if the cost of a full table or index scan is

pkg/sql/opt/xform/coster.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -622,12 +622,17 @@ func (c *coster) ComputeCost(candidate memo.RelExpr, required *physical.Required
622622
// preferable, all else being equal.
623623
cost.C += cpuCostFactor
624624

625-
// Add a one-time cost for any operator with unbounded cardinality. This
626-
// ensures we prefer plans that push limits as far down the tree as possible,
627-
// all else being equal.
628-
//
629-
// Also add a cost flag for unbounded cardinality.
630-
if candidate.Relational().Cardinality.IsUnbounded() {
625+
// Ratchet the max cardinality and add a one-time cost for any operator with
626+
// unbounded cardinality. This ensures we prefer plans that push limits as
627+
// far down the tree as possible, all else being equal. Also add a cost flag
628+
// for unbounded cardinality.
629+
card := candidate.Relational().Cardinality
630+
if candidate.Op() != opt.ExplainOp {
631+
// Do not ratchet the max cardinality for EXPLAIN so that we retain the
632+
// max cardinality of that we would get without EXPLAIN.
633+
cost.RatchetMaxCardinality(card.Max)
634+
}
635+
if card.IsUnbounded() {
631636
cost.C += cpuCostFactor
632637
if c.evalCtx.SessionData().OptimizerPreferBoundedCardinality {
633638
cost.Flags.UnboundedCardinality = true

pkg/sql/plan.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,9 @@ type planTop struct {
356356
// avoidBuffering, when set, causes the execution to avoid buffering
357357
// results.
358358
avoidBuffering bool
359+
// avoidVectorization, when set, causes the execution to avoid using
360+
// vectorized execution.
361+
avoidVectorization bool
359362

360363
// If we are collecting query diagnostics, flow information, including
361364
// diagrams, are saved here.

pkg/sql/plan_opt.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,15 @@ func (opc *optPlanningCtx) runExecBuilder(
961961
if opc.gf.Initialized() {
962962
planTop.instrumentation.planGist = opc.gf.PlanGist()
963963
}
964-
planTop.instrumentation.costEstimate = mem.RootExpr().(memo.RelExpr).Cost().C
964+
965+
cost := mem.RootExpr().(memo.RelExpr).Cost()
966+
if cost.MaxCardinality() <= 1 {
967+
// Use the row-by-row engine if the entire plan is guaranteed to operate
968+
// on one row or less.
969+
planTop.avoidVectorization = true
970+
}
971+
planTop.instrumentation.costEstimate = cost.C
972+
965973
available := mem.RootExpr().(memo.RelExpr).Relational().Statistics().Available
966974
planTop.instrumentation.statsAvailable = available
967975
if available {

0 commit comments

Comments
 (0)