From 345049025e66aa167328bfb122b99f528028f47d Mon Sep 17 00:00:00 2001 From: qw4990 Date: Mon, 12 Dec 2022 17:32:36 +0800 Subject: [PATCH 1/4] fixup --- planner/core/common_plans.go | 20 ++++++++++++++++++-- types/explain_format.go | 3 +++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index 73bb25e0d874c..5fd805d31b728 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -742,6 +742,8 @@ func (e *Explain) prepareSchema() error { } case format == types.ExplainFormatTrueCardCost: fieldNames = []string{"id", "estRows", "estCost", "costFormula", "actRows", "task", "access object", "execution info", "operator info", "memory", "disk"} + case format == types.ExplainFormatCostTrace: + fieldNames = []string{"id", "estRows", "estCost", "costFormula", "task", "access object", "operator info"} case (format == types.ExplainFormatROW || format == types.ExplainFormatBrief) && (e.Analyze || e.RuntimeStatsColl != nil): fieldNames = []string{"id", "estRows", "actRows", "task", "access object", "execution info", "operator info", "memory", "disk"} case format == types.ExplainFormatDOT: @@ -813,8 +815,18 @@ func (e *Explain) RenderResult() error { } } + if strings.ToLower(e.Format) == types.ExplainFormatCostTrace { + if pp, ok := e.TargetPlan.(PhysicalPlan); ok { + // record all cost formulas + if _, err := getPlanCost(pp, property.RootTaskType, + NewDefaultPlanCostOption().WithCostFlag(CostFlagRecalculate|CostFlagTrace)); err != nil { + return err + } + } + } + switch strings.ToLower(e.Format) { - case types.ExplainFormatROW, types.ExplainFormatBrief, types.ExplainFormatVerbose, types.ExplainFormatTrueCardCost: + case types.ExplainFormatROW, types.ExplainFormatBrief, types.ExplainFormatVerbose, types.ExplainFormatTrueCardCost, types.ExplainFormatCostTrace: if e.Rows == nil || e.Analyze { flat := FlattenPhysicalPlan(e.TargetPlan, true) e.explainFlatPlanInRowFormat(flat) @@ -1005,9 +1017,13 @@ func (e *Explain) prepareOperatorInfo(p Plan, taskType, id string) { row = append(row, actRows, taskType, accessObject, analyzeInfo, operatorInfo, memoryInfo, diskInfo) } else { row = []string{id, estRows} - if strings.ToLower(e.Format) == types.ExplainFormatVerbose || strings.ToLower(e.Format) == types.ExplainFormatTrueCardCost { + if strings.ToLower(e.Format) == types.ExplainFormatVerbose || strings.ToLower(e.Format) == types.ExplainFormatTrueCardCost || + strings.ToLower(e.Format) == types.ExplainFormatCostTrace { row = append(row, estCost) } + if strings.ToLower(e.Format) == types.ExplainFormatCostTrace { + row = append(row, costFormula) + } row = append(row, taskType, accessObject, operatorInfo) } e.Rows = append(e.Rows, row) diff --git a/types/explain_format.go b/types/explain_format.go index 00bb9ac1e4336..9ef1dd0ccb975 100644 --- a/types/explain_format.go +++ b/types/explain_format.go @@ -35,6 +35,8 @@ var ( ExplainFormatBinary = "binary" // ExplainFormatTiDBJSON warp the default result in JSON format ExplainFormatTiDBJSON = "tidb_json" + // ExplainFormatCostTrace prints the cost and cost formula of each operator. + ExplainFormatCostTrace = "cost_trace" // ExplainFormats stores the valid formats for explain statement, used by validator. ExplainFormats = []string{ @@ -48,5 +50,6 @@ var ( ExplainFormatTrueCardCost, ExplainFormatBinary, ExplainFormatTiDBJSON, + ExplainFormatCostTrace, } ) From d6a2fc711ead8ebd7ea2925e2da3995cd0864e7c Mon Sep 17 00:00:00 2001 From: qw4990 Date: Mon, 12 Dec 2022 18:37:17 +0800 Subject: [PATCH 2/4] fiuxp --- planner/core/cbo_test.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/planner/core/cbo_test.go b/planner/core/cbo_test.go index af4aa836d335a..32827095e7ca6 100644 --- a/planner/core/cbo_test.go +++ b/planner/core/cbo_test.go @@ -57,6 +57,25 @@ func loadTableStats(fileName string, dom *domain.Domain) error { return nil } +func TestExplainCostTrace(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("create table t (a int)") + + tk.MustExec("set tidb_cost_model_version=2") + tk.MustQuery("explain format='cost_trace' select * from t").Check(testkit.Rows( + `TableReader_5 10000.00 177906.67 ((scan(10000*logrowsize(32)*tikv_scan_factor(40.7))) + (net(10000*rowsize(16)*tidb_kv_net_factor(3.96))))/15.00 root data:TableFullScan_4`, + `└─TableFullScan_4 10000.00 2035000.00 scan(10000*logrowsize(32)*tikv_scan_factor(40.7)) cop[tikv] table:t keep order:false, stats:pseudo`)) + + tk.MustExec("set tidb_cost_model_version=1") + tk.MustQuery("explain format='cost_trace' select * from t").Check(testkit.Rows( + // cost trace on model ver1 is not supported + `TableReader_5 10000.00 34418.00 N/A root data:TableFullScan_4`, + `└─TableFullScan_4 10000.00 435000.00 N/A cop[tikv] table:t keep order:false, stats:pseudo`, + )) +} + func TestExplainAnalyze(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) From 5de1949fb32786b7c786c56fbfa7040a21405cff Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 13 Dec 2022 10:53:38 +0800 Subject: [PATCH 3/4] fiuxp --- planner/core/common_plans.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index 5fd805d31b728..f11f60b95cfe5 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -743,7 +743,11 @@ func (e *Explain) prepareSchema() error { case format == types.ExplainFormatTrueCardCost: fieldNames = []string{"id", "estRows", "estCost", "costFormula", "actRows", "task", "access object", "execution info", "operator info", "memory", "disk"} case format == types.ExplainFormatCostTrace: - fieldNames = []string{"id", "estRows", "estCost", "costFormula", "task", "access object", "operator info"} + if e.Analyze || e.RuntimeStatsColl != nil { + fieldNames = []string{"id", "estRows", "estCost", "costFormula", "actRows", "task", "access object", "execution info", "operator info", "memory", "disk"} + } else { + fieldNames = []string{"id", "estRows", "estCost", "costFormula", "task", "access object", "operator info"} + } case (format == types.ExplainFormatROW || format == types.ExplainFormatBrief) && (e.Analyze || e.RuntimeStatsColl != nil): fieldNames = []string{"id", "estRows", "actRows", "task", "access object", "execution info", "operator info", "memory", "disk"} case format == types.ExplainFormatDOT: @@ -817,7 +821,7 @@ func (e *Explain) RenderResult() error { if strings.ToLower(e.Format) == types.ExplainFormatCostTrace { if pp, ok := e.TargetPlan.(PhysicalPlan); ok { - // record all cost formulas + // trigger getPlanCost again with CostFlagTrace to record all cost formulas if _, err := getPlanCost(pp, property.RootTaskType, NewDefaultPlanCostOption().WithCostFlag(CostFlagRecalculate|CostFlagTrace)); err != nil { return err @@ -1007,10 +1011,10 @@ func (e *Explain) prepareOperatorInfo(p Plan, taskType, id string) { var row []string if e.Analyze || e.RuntimeStatsColl != nil { row = []string{id, estRows} - if strings.ToLower(e.Format) == types.ExplainFormatVerbose || strings.ToLower(e.Format) == types.ExplainFormatTrueCardCost { + if strings.ToLower(e.Format) == types.ExplainFormatVerbose || strings.ToLower(e.Format) == types.ExplainFormatTrueCardCost || strings.ToLower(e.Format) == types.ExplainFormatCostTrace { row = append(row, estCost) } - if strings.ToLower(e.Format) == types.ExplainFormatTrueCardCost { + if strings.ToLower(e.Format) == types.ExplainFormatTrueCardCost || strings.ToLower(e.Format) == types.ExplainFormatCostTrace { row = append(row, costFormula) } actRows, analyzeInfo, memoryInfo, diskInfo := getRuntimeInfoStr(e.ctx, p, e.RuntimeStatsColl) From 10eca872e482a46248b904ae4eb9ec77b5e8fcc6 Mon Sep 17 00:00:00 2001 From: qw4990 Date: Tue, 13 Dec 2022 11:39:20 +0800 Subject: [PATCH 4/4] fiuxp --- planner/core/cbo_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/planner/core/cbo_test.go b/planner/core/cbo_test.go index 32827095e7ca6..8448a66cd0bf0 100644 --- a/planner/core/cbo_test.go +++ b/planner/core/cbo_test.go @@ -62,11 +62,16 @@ func TestExplainCostTrace(t *testing.T) { tk := testkit.NewTestKit(t, store) tk.MustExec("use test") tk.MustExec("create table t (a int)") + tk.MustExec("insert into t values (1)") tk.MustExec("set tidb_cost_model_version=2") tk.MustQuery("explain format='cost_trace' select * from t").Check(testkit.Rows( `TableReader_5 10000.00 177906.67 ((scan(10000*logrowsize(32)*tikv_scan_factor(40.7))) + (net(10000*rowsize(16)*tidb_kv_net_factor(3.96))))/15.00 root data:TableFullScan_4`, `└─TableFullScan_4 10000.00 2035000.00 scan(10000*logrowsize(32)*tikv_scan_factor(40.7)) cop[tikv] table:t keep order:false, stats:pseudo`)) + tk.MustQuery("explain analyze format='cost_trace' select * from t").CheckAt([]int{0, 1, 2, 3, 4}, [][]interface{}{ + {"TableReader_5", "10000.00", "177906.67", "((scan(10000*logrowsize(32)*tikv_scan_factor(40.7))) + (net(10000*rowsize(16)*tidb_kv_net_factor(3.96))))/15.00", "1"}, + {"└─TableFullScan_4", "10000.00", "2035000.00", "scan(10000*logrowsize(32)*tikv_scan_factor(40.7))", "1"}, + }) tk.MustExec("set tidb_cost_model_version=1") tk.MustQuery("explain format='cost_trace' select * from t").Check(testkit.Rows( @@ -74,6 +79,10 @@ func TestExplainCostTrace(t *testing.T) { `TableReader_5 10000.00 34418.00 N/A root data:TableFullScan_4`, `└─TableFullScan_4 10000.00 435000.00 N/A cop[tikv] table:t keep order:false, stats:pseudo`, )) + tk.MustQuery("explain analyze format='cost_trace' select * from t").CheckAt([]int{0, 1, 2, 3, 4}, [][]interface{}{ + {"TableReader_5", "10000.00", "34418.00", "N/A", "1"}, + {"└─TableFullScan_4", "10000.00", "435000.00", "N/A", "1"}, + }) } func TestExplainAnalyze(t *testing.T) {