Skip to content
Draft
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
711 changes: 711 additions & 0 deletions docs/design/2026-07-01-read-billing-demo-ru-model.md

Large diffs are not rendered by default.

29 changes: 22 additions & 7 deletions pkg/executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -366,11 +366,12 @@ type ExecStmt struct {
Ctx sessionctx.Context

// LowerPriority represents whether to lower the execution priority of a query.
LowerPriority bool
isPreparedStmt bool
isSelectForUpdate bool
retryCount uint
retryStartTime time.Time
LowerPriority bool
isPreparedStmt bool
isSelectForUpdate bool
resolvedPreparedStmt ast.StmtNode
retryCount uint
retryStartTime time.Time

// Phase durations are splited into two parts: 1. trying to lock keys (but
// failed); 2. the final iteration of the retry loop. Here we use
Expand Down Expand Up @@ -770,11 +771,19 @@ func (a *ExecStmt) inheritContextFromExecuteStmt() {
a.Ctx.SetValue(sessionctx.QueryString, executePlan.Stmt.Text())
a.OutputNames = executePlan.OutputNames()
a.isPreparedStmt = true
a.resolvedPreparedStmt = executePlan.Stmt
a.Plan = executePlan.Plan
a.Ctx.GetSessionVars().StmtCtx.SetPlan(executePlan.Plan)
}
}

func (a *ExecStmt) readBillingDemoStmtNode() ast.StmtNode {
if a.resolvedPreparedStmt != nil {
return a.resolvedPreparedStmt
}
return a.StmtNode
}

func (a *ExecStmt) getSQLForProcessInfo() string {
sql := a.Text()
if simple, ok := a.Plan.(*plannercore.Simple); ok && simple.Statement != nil {
Expand Down Expand Up @@ -1689,10 +1698,14 @@ func (a *ExecStmt) FinishExecuteStmt(txnTS uint64, err error, hasMoreResults boo
}

a.finalizeStatementRUV2Metrics()
// Lazy SELECT metrics are emitted when the record set is closed. If a
// client abandons a result without closing/draining it, this first demo can
// miss that statement instead of guessing an incomplete status.
readBillingDemoStats := plannercore.RecordReadBillingDemoForStatement(a.Ctx, a.Plan, a.readBillingDemoStmtNode(), err)
a.updateNetworkTrafficStatsAndMetrics()
// `LowSlowQuery` and `SummaryStmt` must be called before recording `PrevStmt`.
a.LogSlowQuery(txnTS, succ, hasMoreResults)
a.SummaryStmt(succ)
a.SummaryStmt(succ, readBillingDemoStats)
a.observeStmtFinishedForTopProfiling()
a.UpdatePlanCacheRuntimeInfo()
if sessVars.StmtCtx.IsTiFlash.Load() {
Expand Down Expand Up @@ -2179,7 +2192,7 @@ func (digest planDigestAlias) planDigestDumpTriggerCheck(config *traceevent.Dump
}

// SummaryStmt collects statements for information_schema.statements_summary
func (a *ExecStmt) SummaryStmt(succ bool) {
func (a *ExecStmt) SummaryStmt(succ bool, readBillingDemoStats stmtsummary.ReadBillingDemoStatementStats) {
sessVars := a.Ctx.GetSessionVars()
var userString string
if sessVars.User != nil {
Expand Down Expand Up @@ -2283,6 +2296,8 @@ func (a *ExecStmt) SummaryStmt(succ bool) {
stmtExecInfo.KeyspaceID = keyspaceID
stmtExecInfo.RUDetail = ruDetail
stmtExecInfo.TotalRUV2 = calculateStatementTotalRUV2(sessVars.RUV2Metrics, sessVars.RUV2Weights(), ruDetail)
stmtExecInfo.ReadBillingDemoStats = readBillingDemoStats
stmtExecInfo.ReadBillingDemoBaseUnits = readBillingDemoStats.Totals
stmtExecInfo.ResourceGroupName = sessVars.StmtCtx.ResourceGroupName
stmtExecInfo.CPUUsages = sessVars.SQLCPUUsages.GetCPUUsages()
stmtExecInfo.PlanCacheUnqualified = sessVars.StmtCtx.PlanCacheUnqualified()
Expand Down
8 changes: 8 additions & 0 deletions pkg/executor/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2616,10 +2616,18 @@ func (b *executorBuilder) buildMemTable(v *physicalop.PhysicalMemTable) exec.Exe
case strings.ToLower(infoschema.TableStatementsSummary),
strings.ToLower(infoschema.TableStatementsSummaryHistory),
strings.ToLower(infoschema.TableStatementsSummaryEvicted),
strings.ToLower(infoschema.TableStatementsSummaryReadBillingDemoBaseUnits),
strings.ToLower(infoschema.TableStatementsSummaryHistoryReadBillingDemoBaseUnits),
strings.ToLower(infoschema.TableStatementsSummaryReadBillingDemoStatus),
strings.ToLower(infoschema.TableStatementsSummaryHistoryReadBillingDemoStatus),
strings.ToLower(infoschema.TableTiDBStatementsStats),
strings.ToLower(infoschema.ClusterTableStatementsSummary),
strings.ToLower(infoschema.ClusterTableStatementsSummaryHistory),
strings.ToLower(infoschema.ClusterTableStatementsSummaryEvicted),
strings.ToLower(infoschema.ClusterTableStatementsSummaryReadBillingDemoBaseUnits),
strings.ToLower(infoschema.ClusterTableStatementsSummaryHistoryReadBillingDemoBaseUnits),
strings.ToLower(infoschema.ClusterTableStatementsSummaryReadBillingDemoStatus),
strings.ToLower(infoschema.ClusterTableStatementsSummaryHistoryReadBillingDemoStatus),
strings.ToLower(infoschema.ClusterTableTiDBStatementsStats):
var extractor *plannercore.StatementsSummaryExtractor
if v.Extractor != nil {
Expand Down
3 changes: 3 additions & 0 deletions pkg/executor/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ func (c *Compiler) Compile(ctx context.Context, stmtNode ast.StmtNode) (_ *ExecS
OutputNames: names,
Ti: &TelemetryInfo{},
}
if preparedObj != nil && preparedObj.PreparedAst != nil {
stmt.resolvedPreparedStmt = preparedObj.PreparedAst.Stmt
}
// Use cached plan if possible.
if preparedObj != nil && plannercore.IsSafeToReusePointGetExecutor(c.Ctx, is, preparedObj) {
if exec, isExec := finalPlan.(*plannercore.Execute); isExec {
Expand Down
Loading
Loading