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

infoschema: add plan digest to slow log and slow_query (#14000) #14292

Merged
merged 1 commit into from
Jan 1, 2020
Merged
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
13 changes: 13 additions & 0 deletions executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,7 @@ func (a *ExecStmt) LogSlowQuery(txnTS uint64, succ bool, hasMoreResults bool) {
statsInfos := plannercore.GetStatsInfo(a.Plan)
memMax := sessVars.StmtCtx.MemTracker.MaxConsumed()
_, digest := sessVars.StmtCtx.SQLDigest()
_, planDigest := getPlanDigest(a.Ctx, a.Plan)
slowItems := &variable.SlowQueryLogItems{
TxnTS: txnTS,
SQL: sql.String(),
Expand All @@ -703,6 +704,7 @@ func (a *ExecStmt) LogSlowQuery(txnTS uint64, succ bool, hasMoreResults bool) {
MemMax: memMax,
Succ: succ,
Plan: getPlanTree(a.Plan),
PlanDigest: planDigest,
Prepared: a.isPreparedStmt,
HasMoreResults: hasMoreResults,
}
Expand Down Expand Up @@ -751,6 +753,17 @@ func getPlanTree(p plannercore.Plan) string {
return variable.SlowLogPlanPrefix + planTree + variable.SlowLogPlanSuffix
}

// getPlanDigest will try to get the select plan tree if the plan is select or the select plan of delete/update/insert statement.
func getPlanDigest(sctx sessionctx.Context, p plannercore.Plan) (normalized, planDigest string) {
normalized, planDigest = sctx.GetSessionVars().StmtCtx.GetPlanDigest()
if len(normalized) > 0 {
return
}
normalized, planDigest = plannercore.NormalizePlan(p)
sctx.GetSessionVars().StmtCtx.SetPlanDigest(normalized, planDigest)
return
}

// SummaryStmt collects statements for performance_schema.events_statements_summary_by_digest
func (a *ExecStmt) SummaryStmt() {
sessVars := a.Ctx.GetSessionVars()
Expand Down
5 changes: 5 additions & 0 deletions infoschema/slow_log.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ var slowQueryCols = []columnInfo{
{variable.SlowLogMemMax, mysql.TypeLonglong, 20, 0, nil, nil},
{variable.SlowLogSucc, mysql.TypeTiny, 1, 0, nil, nil},
{variable.SlowLogPlan, mysql.TypeLongBlob, types.UnspecifiedLength, 0, nil, nil},
{variable.SlowLogPlanDigest, mysql.TypeVarchar, 128, 0, nil, nil},
{variable.SlowLogPrevStmt, mysql.TypeLongBlob, types.UnspecifiedLength, 0, nil, nil},
{variable.SlowLogQuerySQLStr, mysql.TypeLongBlob, types.UnspecifiedLength, 0, nil, nil},
}
Expand Down Expand Up @@ -240,6 +241,7 @@ type slowQueryTuple struct {
isInternal bool
succ bool
plan string
planDigest string
}

func (st *slowQueryTuple) setFieldValue(tz *time.Location, field, value string, lineNum int) error {
Expand Down Expand Up @@ -341,6 +343,8 @@ func (st *slowQueryTuple) setFieldValue(tz *time.Location, field, value string,
st.succ, err = strconv.ParseBool(value)
case variable.SlowLogPlan:
st.plan = value
case variable.SlowLogPlanDigest:
st.planDigest = value
case variable.SlowLogQuerySQLStr:
st.sql = value
}
Expand Down Expand Up @@ -403,6 +407,7 @@ func (st *slowQueryTuple) convertToDatumRow() []types.Datum {
record = append(record, types.NewIntDatum(0))
}
record = append(record, types.NewStringDatum(parsePlan(st.plan)))
record = append(record, types.NewStringDatum(st.planDigest))
record = append(record, types.NewStringDatum(st.prevStmt))
record = append(record, types.NewStringDatum(st.sql))
return record
Expand Down
4 changes: 3 additions & 1 deletion infoschema/slow_log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func (s *testSuite) TestParseSlowLogFile(c *C) {
# Cop_wait_avg: 0.05 Cop_wait_p90: 0.6 Cop_wait_max: 0.8 Cop_wait_addr: 0.0.0.0:20160
# Mem_max: 70724
# Succ: false
# Plan_digest: 60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4
# Prev_stmt: update t set i = 1;
select * from t;`)
reader := bufio.NewReader(slowLog)
Expand All @@ -55,7 +56,7 @@ select * from t;`)
}
recordString += str
}
expectRecordString := "2019-04-28 15:24:04.309074,405888132465033227,,,0,0.216905,0,0,0,0,0,0,0,,0,0,0,0,0,0,0.021,0,0,0,1,637,0,,,1,42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772,t1:1,t2:2,0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,0,,update t set i = 1;,select * from t;"
expectRecordString := "2019-04-28 15:24:04.309074,405888132465033227,,,0,0.216905,0,0,0,0,0,0,0,,0,0,0,0,0,0,0.021,0,0,0,1,637,0,,,1,42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772,t1:1,t2:2,0.1,0.2,0.03,127.0.0.1:20160,0.05,0.6,0.8,0.0.0.0:20160,70724,0,,60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4,update t set i = 1;,select * from t;"
c.Assert(expectRecordString, Equals, recordString)

// fix sql contain '# ' bug
Expand Down Expand Up @@ -166,6 +167,7 @@ select * from t
# Cop_proc_avg: 0.1 Cop_proc_p90: 0.2 Cop_proc_max: 0.03
# Cop_wait_avg: 0.05 Cop_wait_p90: 0.6 Cop_wait_max: 0.8
# Mem_max: 70724
# Plan_digest: 60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4
select * from t;`)
scanner := bufio.NewReader(slowLog)
loc, err := time.LoadLocation("Asia/Shanghai")
Expand Down
5 changes: 3 additions & 2 deletions infoschema/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,7 @@ func (s *testTableSuite) TestSlowQuery(c *C) {
# Mem_max: 70724
# Succ: true
# Plan: abcd
# Plan_digest: 60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4
# Prev_stmt: update t set i = 2;
select * from t_slim;`))
c.Assert(f.Sync(), IsNil)
Expand All @@ -488,10 +489,10 @@ select * from t_slim;`))
tk.MustExec("set time_zone = '+08:00';")
re := tk.MustQuery("select * from information_schema.slow_query")
re.Check(testutil.RowsWithSep("|",
"2019-02-12 19:33:56.571953|406315658548871171|root|127.0.0.1|6|4.895492|0.4|0.2|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.161|0.101|0.092|1.72|1|100001|100000|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|1|abcd|update t set i = 2;|select * from t_slim;"))
"2019-02-12 19:33:56.571953|406315658548871171|root|127.0.0.1|6|4.895492|0.4|0.2|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.161|0.101|0.092|1.72|1|100001|100000|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|1|abcd|60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4|update t set i = 2;|select * from t_slim;"))
tk.MustExec("set time_zone = '+00:00';")
re = tk.MustQuery("select * from information_schema.slow_query")
re.Check(testutil.RowsWithSep("|", "2019-02-12 11:33:56.571953|406315658548871171|root|127.0.0.1|6|4.895492|0.4|0.2|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.161|0.101|0.092|1.72|1|100001|100000|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|1|abcd|update t set i = 2;|select * from t_slim;"))
re.Check(testutil.RowsWithSep("|", "2019-02-12 11:33:56.571953|406315658548871171|root|127.0.0.1|6|4.895492|0.4|0.2|0.19|0.21|0.01|0|0.18|[txnLock]|0.03|0|15|480|1|8|0.161|0.101|0.092|1.72|1|100001|100000|test||0|42a1c8aae6f133e934d4bf0147491709a8812ea05ff8819ec522780fe657b772|t1:1,t2:2|0.1|0.2|0.03|127.0.0.1:20160|0.05|0.6|0.8|0.0.0.0:20160|70724|1|abcd|60e9378c746d9a2be1c791047e008967cf252eb6de9167ad3aa6098fa2d523f4|update t set i = 2;|select * from t_slim;"))

// Test for long query.
_, err = f.Write([]byte(`
Expand Down
4 changes: 3 additions & 1 deletion planner/core/testdata/plan_normalized_suite_in.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"update t1 set a=a+1",
"update t1 set a=a+1 where a>0",
"delete from t1",
"delete from t1 where a>0 and b=1 and c!=2"
"delete from t1 where a>0 and b=1 and c!=2",
"create table t1_tmp (a int)",
"alter table t1_tmp add column c int"
]
}
]
12 changes: 12 additions & 0 deletions planner/core/testdata/plan_normalized_suite_out.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,18 @@
" └─Selection_10 cop ne(test.t1.c, ?)",
" └─TableScan_8 cop table:t1, keep order:false"
]
},
{
"SQL": "create table t1_tmp (a int)",
"Plan": [
""
]
},
{
"SQL": "alter table t1_tmp add column c int",
"Plan": [
""
]
}
]
}
Expand Down
13 changes: 13 additions & 0 deletions sessionctx/stmtctx/stmtctx.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ type StatementContext struct {
lockWaitStartTime *time.Time // LockWaitStartTime stores the pessimistic lock wait start time
PessimisticLockWaited int32
LockKeysDuration time.Duration
// planNormalized use for cache the normalized plan, avoid duplicate builds.
planNormalized string
planDigest string
}

// GetNowTsCached getter for nowTs, if not set get now time and cache it
Expand All @@ -162,6 +165,16 @@ func (sc *StatementContext) SQLDigest() (normalized, sqlDigest string) {
return sc.digestMemo.normalized, sc.digestMemo.digest
}

// GetPlanDigest gets the normalized plan and plan digest.
func (sc *StatementContext) GetPlanDigest() (normalized, planDigest string) {
return sc.planNormalized, sc.planDigest
}

// SetPlanDigest sets the normalized plan and plan digest.
func (sc *StatementContext) SetPlanDigest(normalized, planDigest string) {
sc.planNormalized, sc.planDigest = normalized, planDigest
}

// TableEntry presents table in db.
type TableEntry struct {
DB string
Expand Down
6 changes: 6 additions & 0 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,8 @@ const (
SlowLogPrevStmt = "Prev_stmt"
// SlowLogPlan is used to record the query plan.
SlowLogPlan = "Plan"
// SlowLogPlanDigest is used to record the query plan digest.
SlowLogPlanDigest = "Plan_digest"
// SlowLogPlanPrefix is the prefix of the plan value.
SlowLogPlanPrefix = ast.TiDBDecodePlan + "('"
// SlowLogPlanSuffix is the suffix of the plan value.
Expand Down Expand Up @@ -1115,6 +1117,7 @@ type SlowQueryLogItems struct {
HasMoreResults bool
PrevStmt string
Plan string
PlanDigest string
}

// SlowLogFormat uses for formatting slow log.
Expand Down Expand Up @@ -1221,6 +1224,9 @@ func (s *SessionVars) SlowLogFormat(logItems *SlowQueryLogItems) string {
if len(logItems.Plan) != 0 {
writeSlowLogItem(&buf, SlowLogPlan, logItems.Plan)
}
if len(logItems.PlanDigest) != 0 {
writeSlowLogItem(&buf, SlowLogPlanDigest, logItems.PlanDigest)
}

if logItems.PrevStmt != "" {
writeSlowLogItem(&buf, SlowLogPrevStmt, logItems.PrevStmt)
Expand Down