server: add http api to get some info of sub-optimal query#10717
server: add http api to get some info of sub-optimal query#10717winoros merged 12 commits intopingcap:masterfrom
Conversation
| terror.Log(err) | ||
| } | ||
|
|
||
| sleep := func(w http.ResponseWriter, d time.Duration) { |
There was a problem hiding this comment.
// 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.
Should we continue or just throw error out?
There was a problem hiding this comment.
can we return a message to indicate the failure of dumping stats for this table?
There was a problem hiding this comment.
write a file like dbname.tblname.stats.err?
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") |
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.
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.
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.
how about "failed to extract table names, sql: %v"
There was a problem hiding this comment.
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.
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.
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.
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.
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.
| _, 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.
| 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.
check err in the above if statement
server/sql_info_fetcher.go
Outdated
| if timeoutString != "" { | ||
| timeout, err = strconv.Atoi(timeoutString) | ||
| } | ||
| if err != nil { |
| jsonTbl, err := sh.getStatsForTable(pair) | ||
| if err != nil { | ||
| terror.Log(err) | ||
| continue |
…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.
So we allow multiple statements? Will it cause problems if we use explain sql?
|
/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 analyzeresult.What is changed and how it works?
Extract table names from SQL.
Dump the statistics of the tables.
Use
show create tableto get the schema of them.Use
Explain/Explain analyzeto 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