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

*: record execute runtime information in slow log #17573

Merged
merged 28 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9840c53
init
crazycs520 Jun 1, 2020
cec70da
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 2, 2020
cb3b2dd
fix test
crazycs520 Jun 2, 2020
1f993f5
Merge branch 'slow-log-plan-info' of https://github.com/crazycs520/ti…
crazycs520 Jun 2, 2020
1a7b7bc
add test1
crazycs520 Jun 2, 2020
5ca3ee8
add test2
crazycs520 Jun 2, 2020
90121f8
fix panic
crazycs520 Jun 2, 2020
73b1026
make test stable
crazycs520 Jun 2, 2020
0fc0940
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 2, 2020
aef298f
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 2, 2020
fd5aa68
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 2, 2020
cd1601b
try to fix test
crazycs520 Jun 2, 2020
d7dd02f
try to fix test race
crazycs520 Jun 2, 2020
8c86eaf
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 2, 2020
5b90223
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 2, 2020
2940cda
open collect runtime information to bench
crazycs520 Jun 3, 2020
45fe779
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 3, 2020
e3da540
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 3, 2020
31faa60
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 3, 2020
7ab3ee7
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 4, 2020
f045368
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 4, 2020
356c847
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 5, 2020
be51049
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 5, 2020
5bc8684
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 8, 2020
de40722
Merge branch 'master' into slow-log-plan-info
qw4990 Jun 8, 2020
be4b51b
close collect runtime information by default
crazycs520 Jun 8, 2020
e758b5c
Merge branch 'master' into slow-log-plan-info
crazycs520 Jun 8, 2020
d4a86d6
fix test
crazycs520 Jun 9, 2020
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
10 changes: 10 additions & 0 deletions expression/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4400,6 +4400,16 @@ func (s *testIntegrationSuite) TestTiDBDecodePlanFunc(c *C) {
"\t └─TableReader_21 \troot\t0 \tdata:Selection_20\n" +
"\t └─Selection_20 \tcop \t0 \tlt(Column#9, NULL), not(isnull(Column#10)), not(isnull(Column#9))\n" +
"\t └─TableScan_19\tcop \t10000\ttable:t2, range:[-inf,+inf], keep order:false, stats:pseudo"))
tk.MustQuery("select tidb_decode_plan('rwPwcTAJNV8xNAkwCTEJZnVuY3M6bWF4KHRlc3QudC5hKS0+Q29sdW1uIzQJMQl0aW1lOj" +
"IyMy45MzXCtXMsIGxvb3BzOjIJMTI4IEJ5dGVzCU4vQQoxCTE2XzE4CTAJMQlvZmZzZXQ6MCwgY291bnQ6MQkxCQlHFDE4LjQyMjJHAAhOL0" +
"EBBCAKMgkzMl8yOAkBlEBpbmRleDpMaW1pdF8yNwkxCQ0+DDYuODUdPSwxLCBycGMgbnVtOiANDAUpGDE1MC44MjQFKjhwcm9jIGtleXM6MA" +
"kxOTgdsgAzAbIAMgFearIAFDU3LjM5NgVKAGwN+BGxIDQJMTNfMjYJMQGgHGFibGU6dCwgCbqwaWR4KGEpLCByYW5nZTooMCwraW5mXSwga2" +
"VlcCBvcmRlcjp0cnVlLCBkZXNjAT8kaW1lOjU2LjY2MR1rJDEJTi9BCU4vQQo=')").Check(testkit.Rows("" +
"\tStreamAgg_14 \troot\t1\tfuncs:max(test.t.a)->Column#4 \t1\ttime:223.935µs, loops:2 \t128 Bytes\tN/A\n" +
"\t└─Limit_18 \troot\t1\toffset:0, count:1 \t1\ttime:218.422µs, loops:2 \tN/A \tN/A\n" +
"\t └─IndexReader_28 \troot\t1\tindex:Limit_27 \t1\ttime:216.85µs, loops:1, rpc num: 1, rpc time:150.824µs, proc keys:0\t198 Bytes\tN/A\n" +
"\t └─Limit_27 \tcop \t1\toffset:0, count:1 \t1\ttime:57.396µs, loops:2 \tN/A \tN/A\n" +
"\t └─IndexScan_26\tcop \t1\ttable:t, index:idx(a), range:(0,+inf], keep order:true, desc\t1\ttime:56.661µs, loops:1 \tN/A \tN/A"))
}

func (s *testIntegrationSuite) TestTiDBInternalFunc(c *C) {
Expand Down
78 changes: 42 additions & 36 deletions planner/core/common_plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,47 @@ func (e *Explain) explainPlanInRowFormat(p Plan, taskType, driverSide, indent st
return
}

func getRuntimeInfo(ctx sessionctx.Context, p Plan) (actRows, analyzeInfo, memoryInfo, diskInfo string) {
runtimeStatsColl := ctx.GetSessionVars().StmtCtx.RuntimeStatsColl
if runtimeStatsColl == nil {
return
}
explainID := p.ExplainID().String()

// There maybe some mock information for cop task to let runtimeStatsColl.Exists(p.ExplainID()) is true.
// So check copTaskEkxecDetail first and print the real cop task information if it's not empty.
if runtimeStatsColl.ExistsCopStats(explainID) {
copstats := runtimeStatsColl.GetCopStats(explainID)
analyzeInfo = copstats.String()
actRows = fmt.Sprint(copstats.GetActRows())
} else if runtimeStatsColl.ExistsRootStats(explainID) {
rootstats := runtimeStatsColl.GetRootStats(explainID)
analyzeInfo = rootstats.String()
actRows = fmt.Sprint(rootstats.GetActRows())
} else {
analyzeInfo = "time:0ns, loops:0"
}
switch p.(type) {
case *PhysicalTableReader, *PhysicalIndexReader, *PhysicalIndexLookUpReader:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about PhysicalIndexMergeReader?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just extract those code from prepareOperatorInfo, I'm not sure whether it is a bug.... @qw4990 PTAL

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can ignore this problem here since it's another thing, the PhysicalIndexMergeReader doesn't support collecting read-stats now. @wjhuang2016 @crazycs520

if s := runtimeStatsColl.GetReaderStats(explainID); s != nil && len(s.String()) > 0 {
analyzeInfo += ", " + s.String()
}
}

memoryInfo = "N/A"
memTracker := ctx.GetSessionVars().StmtCtx.MemTracker.SearchTracker(p.ExplainID().String())
if memTracker != nil {
memoryInfo = memTracker.BytesToString(memTracker.MaxConsumed())
}

diskInfo = "N/A"
diskTracker := ctx.GetSessionVars().StmtCtx.DiskTracker.SearchTracker(p.ExplainID().String())
if diskTracker != nil {
diskInfo = diskTracker.BytesToString(diskTracker.MaxConsumed())
}
return
}

// prepareOperatorInfo generates the following information for every plan:
// operator id, estimated rows, task type, access object and other operator info.
func (e *Explain) prepareOperatorInfo(p Plan, taskType, driverSide, indent string, isLastChild bool) {
Expand All @@ -961,42 +1002,7 @@ func (e *Explain) prepareOperatorInfo(p Plan, taskType, driverSide, indent strin

var row []string
if e.Analyze {
runtimeStatsColl := e.ctx.GetSessionVars().StmtCtx.RuntimeStatsColl
explainID := p.ExplainID().String()
var actRows, analyzeInfo string

// There maybe some mock information for cop task to let runtimeStatsColl.Exists(p.ExplainID()) is true.
// So check copTaskEkxecDetail first and print the real cop task information if it's not empty.
if runtimeStatsColl.ExistsCopStats(explainID) {
copstats := runtimeStatsColl.GetCopStats(explainID)
analyzeInfo = copstats.String()
actRows = fmt.Sprint(copstats.GetActRows())
} else if runtimeStatsColl.ExistsRootStats(explainID) {
rootstats := runtimeStatsColl.GetRootStats(explainID)
analyzeInfo = rootstats.String()
actRows = fmt.Sprint(rootstats.GetActRows())
} else {
analyzeInfo = "time:0ns, loops:0"
}
switch p.(type) {
case *PhysicalTableReader, *PhysicalIndexReader, *PhysicalIndexLookUpReader:
if s := runtimeStatsColl.GetReaderStats(explainID); s != nil && len(s.String()) > 0 {
analyzeInfo += ", " + s.String()
}
}

memoryInfo := "N/A"
memTracker := e.ctx.GetSessionVars().StmtCtx.MemTracker.SearchTracker(p.ExplainID().String())
if memTracker != nil {
memoryInfo = memTracker.BytesToString(memTracker.MaxConsumed())
}

diskInfo := "N/A"
diskTracker := e.ctx.GetSessionVars().StmtCtx.DiskTracker.SearchTracker(p.ExplainID().String())
if diskTracker != nil {
diskInfo = diskTracker.BytesToString(diskTracker.MaxConsumed())
}

actRows, analyzeInfo, memoryInfo, diskInfo := getRuntimeInfo(e.ctx, p)
row = []string{id, estRows, actRows, taskType, accessObject, analyzeInfo, operatorInfo, memoryInfo, diskInfo}
} else {
row = []string{id, estRows, taskType, accessObject, operatorInfo}
Expand Down
3 changes: 2 additions & 1 deletion planner/core/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func (pn *planEncoder) encodePlanTree(p PhysicalPlan) string {
}

func (pn *planEncoder) encodePlan(p PhysicalPlan, isRoot bool, depth int) {
plancodec.EncodePlanNode(depth, p.ID(), p.TP(), isRoot, p.statsInfo().RowCount, p.ExplainInfo(), &pn.buf)
actRows, analyzeInfo, memoryInfo, diskInfo := getRuntimeInfo(p.SCtx(), p)
plancodec.EncodePlanNode(depth, p.ID(), p.TP(), isRoot, p.statsInfo().RowCount, p.ExplainInfo(), actRows, analyzeInfo, memoryInfo, diskInfo, &pn.buf)
pn.encodedPlans[p.ID()] = true

depth++
Expand Down
27 changes: 27 additions & 0 deletions planner/core/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,33 @@ func (s *testPlanNormalize) TestNormalizedPlan(c *C) {
}
}

func (s *testPlanNormalize) TestEncodeDecodePlan(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1,t2")
tk.MustExec("create table t1 (a int key,b int,c int, index (b));")
tk.MustExec("set tidb_enable_collect_execution_info=1;")

tk.Se.GetSessionVars().PlanID = 0
tk.MustExec("select max(a) from t1 where a>0;")
info := tk.Se.ShowProcess()
c.Assert(info, NotNil)
p, ok := info.Plan.(core.Plan)
c.Assert(ok, IsTrue)
encodeStr := core.EncodePlan(p)
planTree, err := plancodec.DecodePlan(encodeStr)
c.Assert(err, IsNil)
result := "" +
"\tStreamAgg_13 \troot\t1\tfuncs:max.*->Column#4 \t0\ttime:0s, loops:0 \t.* Bytes\tN/A\n" +
"\t└─Limit_17 \troot\t1\toffset:0, count:1 \t0\ttime:0s, loops:0 \tN/A \tN/A\n" +
"\t └─TableReader_27 \troot\t1\tdata:Limit_26 \t0\ttime:0s, loops:0 \t.* Bytes \tN/A\n" +
"\t └─Limit_26 \tcop \t1\toffset:0, count:1 \t \ttime:0ns, loops:0\tN/A \tN/A\n" +
"\t └─TableScan_25\tcop \t1\ttable:t1, range:.*, keep order:true, desc, stats:pseudo\t0\ttime:0s, loops:0 \tN/A \tN/A"
planTree = strings.Replace(planTree, "\n", "", -1)
result = strings.Replace(result, "\n", "", -1)
c.Assert(planTree, Matches, result)
}

func (s *testPlanNormalize) TestNormalizedDigest(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
Expand Down
27 changes: 26 additions & 1 deletion util/plancodec/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,19 @@ func (pd *planDecoder) alignFields(planInfos []*planInfo) {
if len(planInfos) == 0 {
return
}
// Align fields length. Some plan may doesn't have runtime info, need append `` to align with other plan fields.
maxLen := -1
for _, p := range planInfos {
if len(p.fields) > maxLen {
maxLen = len(p.fields)
}
}
for _, p := range planInfos {
for len(p.fields) < maxLen {
p.fields = append(p.fields, "")
}
}

fieldsLen := len(planInfos[0].fields)
// Last field no need to align.
fieldsLen--
Expand Down Expand Up @@ -253,7 +266,8 @@ func decodePlanInfo(str string) (*planInfo, error) {
}

// EncodePlanNode is used to encode the plan to a string.
func EncodePlanNode(depth, pid int, planType string, isRoot bool, rowCount float64, explainInfo string, buf *bytes.Buffer) {
func EncodePlanNode(depth, pid int, planType string, isRoot bool, rowCount float64,
explainInfo, actRows, analyzeInfo, memoryInfo, diskInfo string, buf *bytes.Buffer) {
buf.WriteString(strconv.Itoa(depth))
buf.WriteByte(separator)
buf.WriteString(encodeID(planType, pid))
Expand All @@ -267,6 +281,17 @@ func EncodePlanNode(depth, pid int, planType string, isRoot bool, rowCount float
buf.WriteString(strconv.FormatFloat(rowCount, 'f', -1, 64))
buf.WriteByte(separator)
buf.WriteString(explainInfo)
// Check whether has runtime info.
if len(actRows) > 0 || len(analyzeInfo) > 0 || len(memoryInfo) > 0 || len(diskInfo) > 0 {
buf.WriteByte(separator)
buf.WriteString(actRows)
buf.WriteByte(separator)
buf.WriteString(analyzeInfo)
buf.WriteByte(separator)
buf.WriteString(memoryInfo)
buf.WriteByte(separator)
buf.WriteString(diskInfo)
}
buf.WriteByte(lineBreaker)
}

Expand Down