-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
server: add http api to get some info of sub-optimal query #10717
Conversation
terror.Log(err) | ||
} | ||
|
||
sleep := func(w http.ResponseWriter, d time.Duration) { |
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.
// Deprecated: the CloseNotifier interface predates Go's context package.
// New code should use Request.Context instead.
jsonTbl, err := sh.getStatsForTable(pair) | ||
if err != nil { | ||
terror.Log(err) | ||
continue |
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.
Should we continue or just throw error out?
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.
can we return a message to indicate the failure of dumping stats for this table?
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.
write a file like dbname.tblname.stats.err
?
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.
looks OK to me
Codecov Report
@@ Coverage Diff @@
## master #10717 +/- ##
===========================================
Coverage 80.9431% 80.9431%
===========================================
Files 420 420
Lines 89506 89506
===========================================
Hits 72449 72449
Misses 11829 11829
Partials 5228 5228 |
5e5f7c4
to
0b32e29
Compare
func (sh *sqlInfoFetcher) zipInfoForSQL(w http.ResponseWriter, r *http.Request) { | ||
reqCtx := r.Context() | ||
sql := r.FormValue("sql") | ||
pprofTimeString := r.FormValue("pprof_time") |
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.
how about profile_sec
?
server/sql_info_fetcher.go
Outdated
return | ||
} | ||
if pprofTime < 5 { | ||
serveError(w, http.StatusBadRequest, "pprof time is too short") |
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.
I think a best practice for this kind of error message is:
- point out the invalid value
- point out the valid value range
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.
Should we return here if it's an invalid value?
} | ||
pairs, err := sh.extractTableNames(sql) | ||
if err != nil { | ||
serveError(w, http.StatusBadRequest, fmt.Sprintf("invalid SQL text, err: %v", err)) |
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.
how about "failed to extract table names, sql: %v"
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.
But the sql is something given by the user.
jsonTbl, err := sh.getStatsForTable(pair) | ||
if err != nil { | ||
terror.Log(err) | ||
continue |
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.
can we return a message to indicate the failure of dumping stats for this table?
server/sql_info_fetcher.go
Outdated
for pair := range pairs { | ||
err = sh.getShowCreateTable(pair, zw) | ||
if err != nil { | ||
serveError(w, http.StatusInternalServerError, fmt.Sprintf("get schema for %v.%v failed", pair.DBName, pair.TableName)) |
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.
Is it ok that we write error messages and zip formatted data to w
at the same time?
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.
In fact, it's not very ok. The following is the curl result when error arisen.
➜ tidb git:(http-fetch-sql-info) ✗ curl -X POST http://127.0.0.1:10080/debug/sub-optimal-plan -d "sql=select%20*%20from%20t¤t_db=test"
execute SQL failed, err: [planner:1046]No database selected
PK
test.t.json��Aj�0���Z
��i��� [iDe+X������"=C��a��[h�Ϋ?���� V4#��陉�6����Y��Ƣ�}��2
u�B��P�:��Ω��t�⧤���~���ܣ&�Ѭ��ɕ�A�E�t�wc�y�k�m�zl6��aw|�yC����H�؆"v�F�+����ן�7?j\���u�O��P� "f���Ӡa\�����T
XQtest.t.schema.txt*�tru
qqt�qUH(IP��RPH�LP(K,J�H,�02�Tpqus
� Q�
����Tp�s��s�����wq�K:{8��ؖ��Y�&�(8���8�����I�y\���P(%��ip� "f
XQ
test.t.json(%��ipCtest.t.schema.txtPKx�%
But the api debug/zip
did the same thing. #9651
Or we may need to write to a BytesBuffer first then write to ResponseWriter
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.
OK... for simplifying, we can leave it as a further optimization and do it in another PR and please add a TODO here.
server/sql_info_fetcher.go
Outdated
timeoutString := r.FormValue("timeout") | ||
curDB := strings.ToLower(r.FormValue("current_db")) | ||
if curDB != "" { | ||
_, err = sh.s.Execute(reqCtx, fmt.Sprintf("use %v", curDB)) |
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.
_, err = sh.s.Execute(reqCtx, fmt.Sprintf("use %v", curDB)) | |
_, err = sh.s.Execute(reqCtx, "use " + curDB) |
server/sql_info_fetcher.go
Outdated
if curDB != "" { | ||
_, err = sh.s.Execute(reqCtx, fmt.Sprintf("use %v", curDB)) | ||
if err != nil { | ||
serveError(w, http.StatusInternalServerError, fmt.Sprintf("use database failed, err: %v", err)) |
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.
serveError(w, http.StatusInternalServerError, fmt.Sprintf("use database failed, err: %v", err)) | |
serveError(w, http.StatusInternalServerError, fmt.Sprintf("use database %v failed: %v", curDB , err)) |
server/sql_info_fetcher.go
Outdated
if pprofTimeString != "" { | ||
pprofTime, err = strconv.Atoi(pprofTimeString) | ||
} | ||
if err != nil { |
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.
check err
in the above if
statement
server/sql_info_fetcher.go
Outdated
if timeoutString != "" { | ||
timeout, err = strconv.Atoi(timeoutString) | ||
} | ||
if err != nil { |
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.
ditto
jsonTbl, err := sh.getStatsForTable(pair) | ||
if err != nil { | ||
terror.Log(err) | ||
continue |
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.
looks OK to me
…into http-fetch-sql-info
server/sql_info_fetcher.go
Outdated
curDB: curDB, | ||
names: make(map[tableNamePair]struct{}), | ||
} | ||
for _, stmt := range stmts { |
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.
So we allow multiple statements? Will it cause problems if we use explain sql
?
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.
LGTM
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.
LGTM
/run-all-tests |
What problem does this PR solve?
add HTTP api
/sub-optimal-plan?pprof_time=&timeout=
to get some information of one SQL.
If we don't set pprof_time. We'll just get explain result. Otherwise we get
explain analyze
result.What is changed and how it works?
Extract table names from SQL.
Dump the statistics of the tables.
Use
show create table
to get the schema of them.Use
Explain
/Explain analyze
to the result.If we run
explain analyze
, we'll run pprof together to get CPU profile.Check List
Tests
curl -X POST ...
test it).Related changes