-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
planner,executor: support admin show slow
command
#7785
Changes from 5 commits
b77189c
5d9a8fb
ed271b9
133cdc1
d449de7
93a8e75
858a106
3e65995
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,10 +21,12 @@ import ( | |
|
||
"github.com/cznic/mathutil" | ||
"github.com/pingcap/tidb/ast" | ||
"github.com/pingcap/tidb/domain" | ||
"github.com/pingcap/tidb/expression" | ||
"github.com/pingcap/tidb/infoschema" | ||
"github.com/pingcap/tidb/kv" | ||
"github.com/pingcap/tidb/model" | ||
"github.com/pingcap/tidb/mysql" | ||
plannercore "github.com/pingcap/tidb/planner/core" | ||
"github.com/pingcap/tidb/sessionctx" | ||
"github.com/pingcap/tidb/table" | ||
|
@@ -472,6 +474,64 @@ func (e *CheckIndexExec) Next(ctx context.Context, chk *chunk.Chunk) error { | |
return nil | ||
} | ||
|
||
// ShowSlowExec represents the executor of showing the slow queries. | ||
// It is build from the "admin show slow" statement: | ||
// admin show slow top [internal | all] N | ||
// admin show slow recent N | ||
type ShowSlowExec struct { | ||
baseExecutor | ||
|
||
done bool | ||
ShowSlow *ast.ShowSlow | ||
} | ||
|
||
// Open implements the Executor Open interface. | ||
func (e *ShowSlowExec) Open(ctx context.Context) error { | ||
if err := e.baseExecutor.Open(ctx); err != nil { | ||
return errors.Trace(err) | ||
} | ||
return nil | ||
} | ||
|
||
// Next implements the Executor Next interface. | ||
func (e *ShowSlowExec) Next(ctx context.Context, chk *chunk.Chunk) error { | ||
chk.Reset() | ||
if e.done { | ||
return nil | ||
} | ||
|
||
dom := domain.GetDomain(e.ctx) | ||
slowQueries := dom.ShowSlowQuery(e.ShowSlow) | ||
for _, slow := range slowQueries { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the number of rows appended to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So if the result is larger than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we have to use a cursor to record how many slow queries have been returned to the client. |
||
chk.AppendString(0, slow.SQL) | ||
chk.AppendTime(1, types.Time{ | ||
Time: types.FromGoTime(slow.Start), | ||
Type: mysql.TypeTimestamp, | ||
Fsp: types.MaxFsp, | ||
}) | ||
chk.AppendDuration(2, types.Duration{Duration: slow.Duration, Fsp: types.MaxFsp}) | ||
chk.AppendString(3, slow.Detail.String()) | ||
if slow.Succ { | ||
chk.AppendInt64(4, 1) | ||
} else { | ||
chk.AppendInt64(4, 0) | ||
} | ||
chk.AppendUint64(5, slow.ConnID) | ||
chk.AppendUint64(6, slow.TxnTS) | ||
chk.AppendString(7, slow.User) | ||
chk.AppendString(8, slow.DB) | ||
chk.AppendString(9, slow.TableIDs) | ||
chk.AppendString(10, slow.IndexIDs) | ||
if slow.Internal { | ||
chk.AppendInt64(11, 0) | ||
} else { | ||
chk.AppendInt64(11, 1) | ||
} | ||
} | ||
e.done = true | ||
return nil | ||
} | ||
|
||
// SelectLockExec represents a select lock executor. | ||
// It is built from the "SELECT .. FOR UPDATE" or the "SELECT .. LOCK IN SHARE MODE" statement. | ||
// For "SELECT .. FOR UPDATE" statement, it locks every row key from source Executor. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -637,11 +637,34 @@ func (s *testSuite) TestShowTableStatus(c *C) { | |
partition by range(a) | ||
( partition p0 values less than (10), | ||
partition p1 values less than (20), | ||
partition p2 values less than (maxvalue) | ||
partition p2 values less than (maxvalue) | ||
);`) | ||
rs, err = tk.Exec("show table status from test like 'tp';") | ||
c.Assert(errors.ErrorStack(err), Equals, "") | ||
rows, err = session.GetRows4Test(context.Background(), tk.Se, rs) | ||
c.Assert(errors.ErrorStack(err), Equals, "") | ||
c.Assert(rows[0].GetString(16), Equals, "partitioned") | ||
} | ||
|
||
func (s *testSuite) TestShowSlow(c *C) { | ||
tk := testkit.NewTestKit(c, s.store) | ||
tk.MustExec("use test") | ||
tk.MustExec(`drop table if exists t`) | ||
tk.MustExec(`create table t(a bigint)`) | ||
tk.MustQuery(`select sleep(1)`) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We can't assume sleep 1s is a slow query, we need to use cfg.Log.SlowThreshold? |
||
|
||
// Collecting slow queries is asynchronous, wait a while to ensure it's done. | ||
time.Sleep(5 * time.Millisecond) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is 5ms enough? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a retry to make the test stable? |
||
|
||
result := tk.MustQuery(`admin show slow recent 3`) | ||
c.Check(result.Rows(), HasLen, 1) | ||
|
||
result = tk.MustQuery(`admin show slow top 3`) | ||
c.Check(result.Rows(), HasLen, 1) | ||
|
||
result = tk.MustQuery(`admin show slow top internal 3`) | ||
c.Check(result.Rows(), HasLen, 0) | ||
|
||
result = tk.MustQuery(`admin show slow top all 3`) | ||
c.Check(result.Rows(), HasLen, 1) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -501,6 +501,10 @@ func (b *planBuilder) buildAdmin(as *ast.AdminStmt) (Plan, error) { | |
p := &ShowDDLJobQueries{JobIDs: as.JobIDs} | ||
p.SetSchema(buildShowDDLJobQueriesFields()) | ||
ret = p | ||
case ast.AdminShowSlow: | ||
p := &ShowSlow{ShowSlow: as.ShowSlow} | ||
p.SetSchema(buildShowSlowSchema()) | ||
ret = p | ||
default: | ||
return nil, ErrUnsupportedType.GenWithStack("Unsupported ast.AdminStmt(%T) for buildAdmin", as) | ||
} | ||
|
@@ -746,6 +750,23 @@ func buildShowDDLJobQueriesFields() *expression.Schema { | |
return schema | ||
} | ||
|
||
func buildShowSlowSchema() *expression.Schema { | ||
schema := expression.NewSchema(make([]*expression.Column, 0, 11)...) | ||
schema.Append(buildColumn("", "SQL", mysql.TypeVarchar, 256)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too small. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about 1024? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1024 still too small. |
||
schema.Append(buildColumn("", "START", mysql.TypeTimestamp, 64)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too big There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 32? |
||
schema.Append(buildColumn("", "DURATION", mysql.TypeDuration, 64)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too big |
||
schema.Append(buildColumn("", "DETAILS", mysql.TypeVarchar, 256)) | ||
schema.Append(buildColumn("", "SUCC", mysql.TypeTiny, 2)) | ||
schema.Append(buildColumn("", "CONN_ID", mysql.TypeLonglong, 4)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too small. |
||
schema.Append(buildColumn("", "TRANSACTION_TS", mysql.TypeLonglong, 4)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too small |
||
schema.Append(buildColumn("", "USER", mysql.TypeVarchar, 32)) | ||
schema.Append(buildColumn("", "DB", mysql.TypeVarchar, 64)) | ||
schema.Append(buildColumn("", "TABLE_IDS", mysql.TypeVarchar, 64)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too small. |
||
schema.Append(buildColumn("", "INDEX_IDS", mysql.TypeVarchar, 64)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. length is too small. |
||
schema.Append(buildColumn("", "INTERNAL", mysql.TypeTiny, 2)) | ||
return schema | ||
} | ||
|
||
func buildCancelDDLJobsFields() *expression.Schema { | ||
schema := expression.NewSchema(make([]*expression.Column, 0, 2)...) | ||
schema.Append(buildColumn("", "JOB_ID", mysql.TypeVarchar, 64)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about
if len(tableIDs) > len("table_ids:")
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a comment for it already.