-
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
*: improve performance of show variables #5297
Conversation
plan/planbuilder.go
Outdated
@@ -599,6 +601,12 @@ func (b *planBuilder) buildShow(show *ast.ShowStmt) Plan { | |||
for i, col := range p.schema.Columns { | |||
col.Position = i | |||
} | |||
if show.Tp == ast.ShowVariables { |
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.
why not handle this in line 582?
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.
This action should be after schema building.
So it is put after line601~604.
plan/planbuilder.go
Outdated
if b.err != nil { | ||
return p | ||
} | ||
for i, cols := 0, ds.Schema().Columns; i < len(cols); i++ { |
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.
for _, cols := range ds.Schema().Columns
It is better to use a sql like |
PTAL @shenli SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'license' OR Variable_name = 'init_connect';
|
@XuHuaiyu You can add a hint for this query which could reduce the cost of optimizer. |
session.go
Outdated
if s.Value(context.Initing) != nil { | ||
return nil, nil | ||
} | ||
sql := `SELECT VARIABLE_NAME, VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME in (` |
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.
It will be even faster if we remove the IN
condition.
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.
GetAllSysVars does not need in condition, select all is OK.
session.go
Outdated
if s.Value(context.Initing) != nil { | ||
return nil, nil | ||
} | ||
sql := `SELECT VARIABLE_NAME, VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME in (` |
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.
GetAllSysVars does not need in condition, select all is OK.
executor/show.go
Outdated
@@ -87,7 +87,7 @@ func (e *ShowExec) Next(goCtx goctx.Context) (Row, error) { | |||
return row, nil | |||
} | |||
|
|||
func (e *ShowExec) fetchAll() error { | |||
func (e *ShowExec) fetchAll(goCtx goctx.Context) error { |
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.
goctx is useless?
executor/show.go
Outdated
} | ||
if err != nil { | ||
return errors.Trace(err) | ||
} | ||
if !ok { | ||
value, ok = systemVars[v.Name] |
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.
This will do.
if !ok {
value = v.Value
}
executor/show.go
Outdated
if !ok { | ||
value, ok = systemVars[v.Name] | ||
if !ok { | ||
sv, ok2 := variable.SysVars[v.Name] |
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.
ok2 is always true, because v was fetched from SysVars.
executor/show.go
Outdated
value, ok = systemVars[v.Name] | ||
if !ok { | ||
sv, ok2 := variable.SysVars[v.Name] | ||
isUninitializedGlobalVariable := ok2 && sv.Scope|variable.ScopeGlobal > 0 |
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.
as an early bug. "sv.Scope|variable.ScopeGlobal > 0" is always true.
if s.Value(context.Initing) != nil { | ||
return nil, nil | ||
} | ||
sql := `SELECT VARIABLE_NAME, VARIABLE_VALUE FROM %s.%s;` |
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.
Why should we load all global variables from tikv?
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.
This makes no difference for performance,
since SysVars hold almost all the variable names(https://github.com/pingcap/tidb/blob/master/sessionctx/variable/sysvar.go#L99).
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 care about the performance, not the memory consuming. We only need to load the variables that in the show variable
statement.
sessionctx/varsutil/varsutil.go
Outdated
} | ||
if sysVar.Scope == variable.ScopeSession { | ||
return "", variable.ErrIncorrectScope | ||
return "", false, variable.ErrIncorrectScope |
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.
We can move this error to GetGlobalSystemVar
.
Conflicts: sessionctx/varsutil/varsutil.go
executor/show.go
Outdated
} else { | ||
value, err = varsutil.GetGlobalSystemVar(sessionVars, v.Name) | ||
value, ok, err = varsutil.GetScopeNoneSystemVar(v.Name) |
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.
add some comment here. about session scope, global scope and none scope, it is confused.
reset LGTM |
LGTM |
PTAL @winkyao |
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
fix #5126
PTAL @winkyao
Before this commit:
When run
show variables
, TiDB will autorun sqlSELECT VARIABLE_VALUE FROM %s.%s WHERE VARIABLE_NAME="%s";
to fetch the value of every VARIABLE_NAME which
caused bad performance as #5126 described.
After commit:
We get all the data just once hence avoiding the time cost.
On my machine, for sql:
before: 0.59s
after:0.03s