Skip to content

Commit b76bfbc

Browse files
authored
planner: support EXPLAIN ANALYZE FORMAT='ru' (#70371)
ref #70373
1 parent 70323e9 commit b76bfbc

6 files changed

Lines changed: 5068 additions & 5001 deletions

File tree

pkg/executor/explain_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,22 @@ func checkActRows(t *testing.T, tk *testkit.TestKit, sql string, expected []stri
186186
}
187187
}
188188

189+
func checkAnalyzeRUFormat(t *testing.T, tk *testkit.TestKit, sql string, expectedActRows []string) {
190+
t.Helper()
191+
rows := tk.MustQuery("explain analyze format = 'ru' " + sql).Rows()
192+
require.Equal(t, len(expectedActRows), len(rows))
193+
for id, row := range rows {
194+
require.Len(t, row, 7)
195+
require.NotEmpty(t, row[0])
196+
require.NotEmpty(t, row[1])
197+
require.Equal(t, expectedActRows[id], row[2], fmt.Sprintf("error comparing %s", sql))
198+
require.Equal(t, "", row[3])
199+
require.Equal(t, "", row[4])
200+
require.Equal(t, "", row[5])
201+
require.Equal(t, "", row[6])
202+
}
203+
}
204+
189205
func TestCheckActRowsWithUnistore(t *testing.T) {
190206
defer config.RestoreFunc()()
191207
config.UpdateGlobal(func(conf *config.Config) {
@@ -260,6 +276,9 @@ func TestCheckActRowsWithUnistore(t *testing.T) {
260276
for _, test := range tests {
261277
checkActRows(t, tk, test.sql, test.expected)
262278
}
279+
280+
checkAnalyzeRUFormat(t, tk, "select * from t_unistore_act_rows", []string{"4", "4"})
281+
checkAnalyzeRUFormat(t, tk, "select * from t_unistore_act_rows where b > 0", []string{"1", "1", "4"})
263282
}
264283

265284
func TestExplainAnalyzeCTEMemoryAndDiskInfo(t *testing.T) {
@@ -496,6 +515,7 @@ func TestExplainFormatInCtx(t *testing.T) {
496515
types.ExplainFormatTiDBJSON,
497516
types.ExplainFormatCostTrace,
498517
types.ExplainFormatPlanCache,
518+
types.ExplainFormatRU,
499519
}
500520

501521
tk.MustExec("select * from t")

pkg/parser/parser.go

Lines changed: 5003 additions & 5001 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/parser/parser.y

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6070,6 +6070,7 @@ ExplainFormatType:
60706070
| "VERBOSE"
60716071
| "TRUE_CARD_COST"
60726072
| "TIDB_JSON"
6073+
| "RU"
60736074

60746075
SavepointStmt:
60756076
"SAVEPOINT" Identifier

pkg/planner/core/common_plans.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,9 @@ func (e *Explain) prepareSchema() error {
735735
fieldNames = []string{"binary plan"}
736736
case format == types.ExplainFormatTiDBJSON:
737737
fieldNames = []string{"TiDB_JSON"}
738+
case format == types.ExplainFormatRU:
739+
// TODO: Populate RU-specific columns after per-operator RU attribution is available.
740+
fieldNames = []string{"id", "task", "actRows", "selfRU", "cumRU", "cumRU%", "detail"}
738741
case e.Explore:
739742
fieldNames = []string{"statement", "binding_hint", "plan", "plan_digest", "avg_latency", "exec_times", "avg_scan_rows",
740743
"avg_returned_rows", "latency_per_returned_row", "scan_rows_per_returned_row", "recommend", "reason",
@@ -932,6 +935,9 @@ func (e *Explain) RenderResult() error {
932935
return err
933936
}
934937
e.Rows = append(e.Rows, []string{str})
938+
case types.ExplainFormatRU:
939+
flat := FlattenPhysicalPlan(e.TargetPlan, true)
940+
e.Rows = ExplainFlatPlanInRUFormat(flat, e.RuntimeStatsColl)
935941
default:
936942
return errors.Errorf("explain format '%s' is not supported now", e.Format)
937943
}
@@ -1106,6 +1112,38 @@ func prepareOperatorInfo(flatOp *FlatOperator, format string, analyze bool,
11061112
return append(rows, row)
11071113
}
11081114

1115+
// ExplainFlatPlanInRUFormat returns the explain analyze result with RU columns.
1116+
func ExplainFlatPlanInRUFormat(flat *FlatPhysicalPlan, runtimeStatsColl *execdetails.RuntimeStatsColl) (rows [][]string) {
1117+
if flat == nil || len(flat.Main) == 0 || flat.InExplain {
1118+
return
1119+
}
1120+
for _, flatOp := range flat.Main {
1121+
rows = prepareRUOperatorInfo(flatOp, runtimeStatsColl, rows)
1122+
}
1123+
for _, cte := range flat.CTEs {
1124+
for _, flatOp := range cte {
1125+
rows = prepareRUOperatorInfo(flatOp, runtimeStatsColl, rows)
1126+
}
1127+
}
1128+
for _, subQ := range flat.ScalarSubQueries {
1129+
for _, flatOp := range subQ {
1130+
rows = prepareRUOperatorInfo(flatOp, runtimeStatsColl, rows)
1131+
}
1132+
}
1133+
return
1134+
}
1135+
1136+
func prepareRUOperatorInfo(flatOp *FlatOperator, runtimeStatsColl *execdetails.RuntimeStatsColl, rows [][]string) [][]string {
1137+
p := flatOp.Origin
1138+
if p.ExplainID().String() == "_0" {
1139+
return rows
1140+
}
1141+
taskType, id := getExplainIDAndTaskTp(flatOp)
1142+
actRows, _, _, _ := getRuntimeInfoStr(p.SCtx(), p, runtimeStatsColl)
1143+
// TODO: Replace the empty RU columns with real selfRU, cumRU, cumRU%, and detail values.
1144+
return append(rows, []string{id, taskType, actRows, "", "", "", ""})
1145+
}
1146+
11091147
func (e *Explain) prepareOperatorInfoForJSONFormat(p base.Plan, taskType, explainID string) *ExplainInfoForEncode {
11101148
if p.ExplainID().String() == "_0" {
11111149
return nil

pkg/planner/core/planbuilder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5718,6 +5718,9 @@ func (b *PlanBuilder) buildExplainPlan(targetPlan base.Plan, format string, expl
57185718
if format == types.ExplainFormatTrueCardCost && !analyze {
57195719
return nil, errors.Errorf("'explain format=%v' cannot work without 'analyze', please use 'explain analyze format=%v'", format, format)
57205720
}
5721+
if format == types.ExplainFormatRU && !analyze {
5722+
return nil, errors.Errorf("'explain format=%v' cannot work without 'analyze', please use 'explain analyze format=%v'", format, format)
5723+
}
57215724

57225725
p := &Explain{
57235726
TargetPlan: targetPlan,

pkg/types/explain_format.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ var (
4141
ExplainFormatPlanCache = "plan_cache"
4242
// ExplainFormatPlanTree displays the plan in a tree structure format
4343
ExplainFormatPlanTree = "plan_tree"
44+
// ExplainFormatRU is reserved for RU cost output in explain analyze.
45+
ExplainFormatRU = "ru"
4446

4547
// ExplainFormats stores the valid formats for explain statement, used by validator.
4648
ExplainFormats = []string{
@@ -57,5 +59,6 @@ var (
5759
ExplainFormatCostTrace,
5860
ExplainFormatPlanCache,
5961
ExplainFormatPlanTree,
62+
ExplainFormatRU,
6063
}
6164
)

0 commit comments

Comments
 (0)