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 3 fields to statement summary table #14096

Merged
merged 6 commits into from
Dec 19, 2019
Merged
Show file tree
Hide file tree
Changes from 5 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
20 changes: 18 additions & 2 deletions executor/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,13 @@ func (a *recordSet) NewChunk() *chunk.Chunk {

func (a *recordSet) Close() error {
err := a.executor.Close()
// `LowSlowQuery` and `SummaryStmt` must be called before recording `PrevStmt`.
a.stmt.LogSlowQuery(a.txnStartTS, a.lastErr == nil, false)
a.stmt.SummaryStmt()
sessVars := a.stmt.Ctx.GetSessionVars()
pps := types.CloneRow(sessVars.PreparedParams)
sessVars.PrevStmt = FormatSQL(a.stmt.OriginText(), pps)
a.stmt.logAudit()
a.stmt.SummaryStmt()
return err
}

Expand Down Expand Up @@ -859,13 +860,26 @@ func getPlanDigest(sctx sessionctx.Context, p plannercore.Plan) (normalized, pla
// SummaryStmt collects statements for performance_schema.events_statements_summary_by_digest
func (a *ExecStmt) SummaryStmt() {
sessVars := a.Ctx.GetSessionVars()
if sessVars.InRestrictedSQL || !stmtsummary.StmtSummaryByDigestMap.Enabled() {
// Internal SQLs must also be recorded to keep the consistency of `PrevStmt` and `PrevStmtDigest`.
if !stmtsummary.StmtSummaryByDigestMap.Enabled() {
sessVars.SetPrevStmtDigest("")
return
}
stmtCtx := sessVars.StmtCtx
normalizedSQL, digest := stmtCtx.SQLDigest()
costTime := time.Since(sessVars.StartTime)

var prevSQL, prevSQLDigest string
if _, ok := a.StmtNode.(*ast.CommitStmt); ok {
// If prevSQLDigest is not recorded, it means this `commit` is the first SQL once stmt summary is enabled,
// so it's OK just to ignore it.
if prevSQLDigest = sessVars.GetPrevStmtDigest(); len(prevSQLDigest) == 0 {
return
}
prevSQL = sessVars.PrevStmt.String()
}
sessVars.SetPrevStmtDigest(digest)

execDetail := stmtCtx.GetExecDetails()
copTaskInfo := stmtCtx.CopTasksDetails()
memMax := stmtCtx.MemTracker.MaxConsumed()
Expand All @@ -879,6 +893,8 @@ func (a *ExecStmt) SummaryStmt() {
OriginalSQL: a.Text,
NormalizedSQL: normalizedSQL,
Digest: digest,
PrevSQL: prevSQL,
PrevSQLDigest: prevSQLDigest,
User: userString,
TotalLatency: costTime,
ParseLatency: sessVars.DurationParse,
Expand Down
79 changes: 13 additions & 66 deletions infoschema/perfschema/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,10 @@ const tableStagesHistoryLong = "CREATE TABLE if not exists performance_schema."
"NESTING_EVENT_ID BIGINT(20) UNSIGNED," +
"NESTING_EVENT_TYPE ENUM('TRANSACTION','STATEMENT','STAGE'));"

// tableEventsStatementsSummaryByDigest contains the column name definitions for table
// events_statements_summary_by_digest, same as MySQL.
const tableEventsStatementsSummaryByDigest = "CREATE TABLE if not exists " + tableNameEventsStatementsSummaryByDigest + " (" +
// Fields in `events_statements_summary_by_digest` and `events_statements_summary_by_digest_history` are the same.
const fieldsInEventsStatementsSummary = " (" +
"SUMMARY_BEGIN_TIME TIMESTAMP(6) NOT NULL," +
"SUMMARY_END_TIME TIMESTAMP(6) NOT NULL," +
"STMT_TYPE VARCHAR(64) NOT NULL," +
"SCHEMA_NAME VARCHAR(64) DEFAULT NULL," +
"DIGEST VARCHAR(64) NOT NULL," +
Expand Down Expand Up @@ -447,78 +447,25 @@ const tableEventsStatementsSummaryByDigest = "CREATE TABLE if not exists " + tab
"MAX_PREWRITE_REGIONS INT(11) UNSIGNED NOT NULL," +
"AVG_TXN_RETRY DOUBLE NOT NULL," +
"MAX_TXN_RETRY INT(11) UNSIGNED NOT NULL," +
"SUM_BACKOFF_TIMES BIGINT(20) UNSIGNED NOT NULL," +
"BACKOFF_TYPES VARCHAR(1024) DEFAULT NULL," +
"AVG_MEM BIGINT(20) UNSIGNED NOT NULL," +
"MAX_MEM BIGINT(20) UNSIGNED NOT NULL," +
"AVG_AFFECTED_ROWS DOUBLE UNSIGNED NOT NULL," +
"FIRST_SEEN TIMESTAMP(6) NOT NULL," +
"LAST_SEEN TIMESTAMP(6) NOT NULL," +
"QUERY_SAMPLE_TEXT LONGTEXT DEFAULT NULL);"
"QUERY_SAMPLE_TEXT LONGTEXT DEFAULT NULL," +
"PREV_SAMPLE_TEXT LONGTEXT DEFAULT NULL);"

// tableEventsStatementsSummaryByDigest contains the column name definitions for table
AilinKid marked this conversation as resolved.
Show resolved Hide resolved
// events_statements_summary_by_digest, same as MySQL.
const tableEventsStatementsSummaryByDigest = "CREATE TABLE if not exists " + tableNameEventsStatementsSummaryByDigest +
fieldsInEventsStatementsSummary

// tableEventsStatementsSummaryByDigestHistory contains the column name definitions for table
// events_statements_summary_by_digest_history.
const tableEventsStatementsSummaryByDigestHistory = "CREATE TABLE if not exists events_statements_summary_by_digest_history (" +
"SUMMARY_BEGIN_TIME TIMESTAMP(6) NOT NULL," +
"STMT_TYPE VARCHAR(64) NOT NULL," +
"SCHEMA_NAME VARCHAR(64) DEFAULT NULL," +
"DIGEST VARCHAR(64) NOT NULL," +
"DIGEST_TEXT LONGTEXT NOT NULL," +
"TABLE_NAMES TEXT DEFAULT NULL," +
"INDEX_NAMES TEXT DEFAULT NULL," +
"SAMPLE_USER VARCHAR(64) DEFAULT NULL," +
"EXEC_COUNT BIGINT(20) UNSIGNED NOT NULL," +
"SUM_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"MAX_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"MIN_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"AVG_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"AVG_PARSE_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"MAX_PARSE_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"AVG_COMPILE_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COMPILE_LATENCY BIGINT(20) UNSIGNED NOT NULL," +
"COP_TASK_NUM BIGINT(20) UNSIGNED NOT NULL," +
"AVG_COP_PROCESS_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COP_PROCESS_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COP_PROCESS_ADDRESS VARCHAR(256) DEFAULT NULL," +
"AVG_COP_WAIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COP_WAIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COP_WAIT_ADDRESS VARCHAR(256) DEFAULT NULL," +
"AVG_PROCESS_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_PROCESS_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_WAIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_WAIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_BACKOFF_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_BACKOFF_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_TOTAL_KEYS BIGINT(20) UNSIGNED NOT NULL," +
"MAX_TOTAL_KEYS BIGINT(20) UNSIGNED NOT NULL," +
"AVG_PROCESSED_KEYS BIGINT(20) UNSIGNED NOT NULL," +
"MAX_PROCESSED_KEYS BIGINT(20) UNSIGNED NOT NULL," +
"AVG_PREWRITE_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_PREWRITE_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_COMMIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COMMIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_GET_COMMIT_TS_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_GET_COMMIT_TS_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_COMMIT_BACKOFF_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_COMMIT_BACKOFF_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_RESOLVE_LOCK_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_RESOLVE_LOCK_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_LOCAL_LATCH_WAIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"MAX_LOCAL_LATCH_WAIT_TIME BIGINT(20) UNSIGNED NOT NULL," +
"AVG_WRITE_KEYS DOUBLE UNSIGNED NOT NULL," +
"MAX_WRITE_KEYS BIGINT(20) UNSIGNED NOT NULL," +
"AVG_WRITE_SIZE DOUBLE NOT NULL," +
"MAX_WRITE_SIZE BIGINT(20) UNSIGNED NOT NULL," +
"AVG_PREWRITE_REGIONS DOUBLE NOT NULL," +
"MAX_PREWRITE_REGIONS INT(11) UNSIGNED NOT NULL," +
"AVG_TXN_RETRY DOUBLE NOT NULL," +
"MAX_TXN_RETRY INT(11) UNSIGNED NOT NULL," +
"BACKOFF_TYPES VARCHAR(1024) DEFAULT NULL," +
"AVG_MEM BIGINT(20) UNSIGNED NOT NULL," +
"MAX_MEM BIGINT(20) UNSIGNED NOT NULL," +
"AVG_AFFECTED_ROWS DOUBLE UNSIGNED NOT NULL," +
"FIRST_SEEN TIMESTAMP(6) NOT NULL," +
"LAST_SEEN TIMESTAMP(6) NOT NULL," +
"QUERY_SAMPLE_TEXT LONGTEXT DEFAULT NULL);"
const tableEventsStatementsSummaryByDigestHistory = "CREATE TABLE if not exists " + tableNameEventsStatementsSummaryByDigestHistory +
fieldsInEventsStatementsSummary

// tableTiDBProfileCPU contains the columns name definitions for table tidb_profile_cpu
const tableTiDBProfileCPU = "CREATE TABLE IF NOT EXISTS " + tableNameTiDBProfileCPU + " (" +
Expand Down
8 changes: 4 additions & 4 deletions infoschema/perfschema/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,16 +153,16 @@ func (s *testTableSuite) TestStmtSummaryTable(c *C) {
tk.MustExec("commit")
tk.MustQuery(`select stmt_type, schema_name, table_names, index_names, exec_count, cop_task_num, avg_total_keys,
max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions,
max_prewrite_regions, avg_affected_rows, query_sample_text
max_prewrite_regions, avg_affected_rows, query_sample_text, prev_sample_text
from performance_schema.events_statements_summary_by_digest
where digest_text like 'insert into t%'`,
).Check(testkit.Rows("insert test test.t <nil> 1 0 0 0 0 0 0 0 0 0 1 insert into t values(1, 'a')"))
).Check(testkit.Rows("insert test test.t <nil> 1 0 0 0 0 0 0 0 0 0 1 insert into t values(1, 'a') "))
tk.MustQuery(`select stmt_type, schema_name, table_names, index_names, exec_count, cop_task_num, avg_total_keys,
max_total_keys, avg_processed_keys, max_processed_keys, avg_write_keys, max_write_keys, avg_prewrite_regions,
max_prewrite_regions, avg_affected_rows, query_sample_text
max_prewrite_regions, avg_affected_rows, query_sample_text, prev_sample_text
from performance_schema.events_statements_summary_by_digest
where digest_text='commit'`,
).Check(testkit.Rows("commit test <nil> <nil> 1 0 0 0 0 0 2 2 1 1 0 commit"))
).Check(testkit.Rows("commit test <nil> <nil> 1 0 0 0 0 0 2 2 1 1 0 commit insert into t values(1, 'a')"))

tk.MustQuery("select * from t where a=2")
tk.MustQuery(`select stmt_type, schema_name, table_names, index_names, exec_count, cop_task_num, avg_total_keys,
Expand Down
1 change: 1 addition & 0 deletions session/tidb.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ func runStmt(ctx context.Context, sctx sessionctx.Context, s sqlexec.Statement)
// If it is not a select statement, we record its slow log here,
// then it could include the transaction commit time.
if rs == nil {
// `LowSlowQuery` and `SummaryStmt` must be called before recording `PrevStmt`.
s.(*executor.ExecStmt).LogSlowQuery(origTxnCtx.StartTS, err == nil, false)
s.(*executor.ExecStmt).SummaryStmt()
pps := types.CloneRow(sessVars.PreparedParams)
Expand Down
15 changes: 15 additions & 0 deletions sessionctx/variable/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,9 @@ type SessionVars struct {
// PrevStmt is used to store the previous executed statement in the current session.
PrevStmt fmt.Stringer

// prevStmtDigest is used to store the digest of the previous statement in the current session.
prevStmtDigest string

// AllowRemoveAutoInc indicates whether a user can drop the auto_increment column attribute or not.
AllowRemoveAutoInc bool

Expand Down Expand Up @@ -1041,6 +1044,18 @@ func (s *SessionVars) setTxnMode(val string) error {
return nil
}

// SetPrevStmtDigest sets the digest of the previous statement.
func (s *SessionVars) SetPrevStmtDigest(prevStmtDigest string) {
AilinKid marked this conversation as resolved.
Show resolved Hide resolved
s.prevStmtDigest = prevStmtDigest
}

// GetPrevStmtDigest returns the digest of the previous statement.
func (s *SessionVars) GetPrevStmtDigest() string {
// Because `prevStmt` may be truncated, so it's senseless to normalize it.
// Even if `prevStmtDigest` is empty but `prevStmt` is not, just return it anyway.
return s.prevStmtDigest
}

// SetLocalSystemVar sets values of the local variables which in "server" scope.
func SetLocalSystemVar(name string, val string) {
switch name {
Expand Down
Loading