提交 5b5d1604 编写于 作者: martianzhang's avatar martianzhang

use markdownlint format doc

上级 bdb34724
...@@ -38,18 +38,18 @@ import ( ...@@ -38,18 +38,18 @@ import (
func main() { func main() {
// 全局变量 // 全局变量
var sql string // 单条评审指定的sql或explain var sql string // 单条评审指定的 sql 或 explain
sqlCounter := 1 // SQL 计数器 sqlCounter := 1 // SQL 计数器
lineCounter := 1 // 行计数器 lineCounter := 1 // 行计数器
var alterSqls []string // 待评审的SQL中所有ALTER请求 var alterSqls []string // 待评审的 SQL 中所有 ALTER 请求
alterTableTimes := make(map[string]int) // 待评审的SQL中同一经表ALTER请求计数器 alterTableTimes := make(map[string]int) // 待评审的 SQL 中同一经表 ALTER 请求计数器
suggestMerged := make(map[string]map[string]advisor.Rule) // 优化建议去重,key为sql的fingerprint.ID suggestMerged := make(map[string]map[string]advisor.Rule) // 优化建议去重, key 为 sql 的 fingerprint.ID
ex, err := os.Executable() ex, err := os.Executable()
if err != nil { if err != nil {
panic(err) panic(err)
} }
common.BaseDir = filepath.Dir(ex) // binary文件所在路径 common.BaseDir = filepath.Dir(ex) // binary 文件所在路径
// 配置文件&命令行参数解析 // 配置文件&命令行参数解析
err = common.ParseConfig("") err = common.ParseConfig("")
...@@ -61,17 +61,17 @@ func main() { ...@@ -61,17 +61,17 @@ func main() {
advisor.ListHeuristicRules(advisor.HeuristicRules) advisor.ListHeuristicRules(advisor.HeuristicRules)
return return
} }
// 打印支持的SQL重写规则 // 打印支持的 SQL 重写规则
if common.Config.ListRewriteRules { if common.Config.ListRewriteRules {
ast.ListRewriteRules(ast.RewriteRules) ast.ListRewriteRules(ast.RewriteRules)
return return
} }
// 打印所有的测试SQL // 打印所有的测试 SQL
if common.Config.ListTestSqls { if common.Config.ListTestSqls {
advisor.ListTestSQLs() advisor.ListTestSQLs()
return return
} }
// 打印支持的report-type // 打印支持的 report-type
if common.Config.ListReportTypes { if common.Config.ListReportTypes {
common.ListReportTypes() common.ListReportTypes()
return return
...@@ -97,7 +97,7 @@ func main() { ...@@ -97,7 +97,7 @@ func main() {
return return
} }
// 读入待优化SQL,当配置文件或命令行参数未指定SQL时从管道读取 // 读入待优化 SQL ,当配置文件或命令行参数未指定 SQL 时从管道读取
if common.Config.Query == "" { if common.Config.Query == "" {
var data []byte var data []byte
data, err = ioutil.ReadAll(os.Stdin) data, err = ioutil.ReadAll(os.Stdin)
...@@ -123,7 +123,7 @@ func main() { ...@@ -123,7 +123,7 @@ func main() {
switch common.Config.ReportType { switch common.Config.ReportType {
case "html": case "html":
// HTML格式输入CSS加载 // HTML 格式输入 CSS 加载
fmt.Println(common.MarkdownHTMLHeader()) fmt.Println(common.MarkdownHTMLHeader())
case "md2html": case "md2html":
// markdown2html 转换小工具 // markdown2html 转换小工具
...@@ -131,8 +131,8 @@ func main() { ...@@ -131,8 +131,8 @@ func main() {
fmt.Println(common.Markdown2HTML(sql)) fmt.Println(common.Markdown2HTML(sql))
return return
case "explain-digest": case "explain-digest":
// 当用户输入为EXPLAIN信息,只对Explain信息进行分析 // 当用户输入为 EXPLAIN信 息,只对 Explain 信息进行分析
// 注意: 这里只能处理一条SQL的EXPLAIN信息,用户一次反馈多条SQL的EXPLAIN信息无法处理 // 注意: 这里只能处理一条 SQL 的 EXPLAIN 信息,用户一次反馈多条 SQL 的 EXPLAIN 信息无法处理
advisor.DigestExplainText(sql) advisor.DigestExplainText(sql)
return return
case "remove-comment": case "remove-comment":
...@@ -146,11 +146,11 @@ func main() { ...@@ -146,11 +146,11 @@ func main() {
for ; ; sqlCounter++ { for ; ; sqlCounter++ {
var id string // fingerprint.ID var id string // fingerprint.ID
heuristicSuggest := make(map[string]advisor.Rule) // 启发式建议 heuristicSuggest := make(map[string]advisor.Rule) // 启发式建议
expSuggest := make(map[string]advisor.Rule) // EXPLAIN解读 expSuggest := make(map[string]advisor.Rule) // EXPLAIN 解读
idxSuggest := make(map[string]advisor.Rule) // 索引建议 idxSuggest := make(map[string]advisor.Rule) // 索引建议
proSuggest := make(map[string]advisor.Rule) // Profiling信息 proSuggest := make(map[string]advisor.Rule) // Profiling 信息
traceSuggest := make(map[string]advisor.Rule) // Trace信息 traceSuggest := make(map[string]advisor.Rule) // Trace 信息
mysqlSuggest := make(map[string]advisor.Rule) // MySQL返回的ERROR信息 mysqlSuggest := make(map[string]advisor.Rule) // MySQL 返回的 ERROR 信息
if buf == "" { if buf == "" {
common.Log.Debug("buf: %s, sql: %s empty", buf, sql) common.Log.Debug("buf: %s, sql: %s empty", buf, sql)
...@@ -178,15 +178,15 @@ func main() { ...@@ -178,15 +178,15 @@ func main() {
fingerprint := strings.TrimSpace(query.Fingerprint(sql)) fingerprint := strings.TrimSpace(query.Fingerprint(sql))
switch common.Config.ReportType { switch common.Config.ReportType {
case "fingerprint": case "fingerprint":
// SQL指纹 // SQL 指纹
fmt.Println(fingerprint) fmt.Println(fingerprint)
continue continue
case "pretty": case "pretty":
// SQL美化 // SQL 美化
fmt.Println(ast.Pretty(sql, "builtin") + common.Config.Delimiter) fmt.Println(ast.Pretty(sql, "builtin") + common.Config.Delimiter)
continue continue
case "compress": case "compress":
// SQL压缩 // SQL 压缩
fmt.Println(ast.Compress(sql) + common.Config.Delimiter) fmt.Println(ast.Compress(sql) + common.Config.Delimiter)
continue continue
case "ast": case "ast":
...@@ -210,10 +210,10 @@ func main() { ...@@ -210,10 +210,10 @@ func main() {
common.LogIfWarn(err, "") common.LogIfWarn(err, "")
continue continue
default: default:
// SQL签名 // SQL 签名
id = query.Id(fingerprint) id = query.Id(fingerprint)
// 建议去重,减少评审整个文件耗时 // 建议去重,减少评审整个文件耗时
// TODO: 由于 a = 11和a = '11'的fingerprint相同,这里一旦跳过即无法检查有些建议了,如:ARG.003 // TODO: 由于 a = 11 和 a = '11' 的 fingerprint 相同,这里一旦跳过即无法检查有些建议了,如: ARG.003
if _, ok := suggestMerged[id]; ok { if _, ok := suggestMerged[id]; ok {
continue continue
} }
...@@ -230,7 +230,7 @@ func main() { ...@@ -230,7 +230,7 @@ func main() {
switch stmt.(type) { switch stmt.(type) {
case *sqlparser.DDL: case *sqlparser.DDL:
// 因为vitess的parser对于DDL语法支持不好,通过在测试环境执行辅助进行语法检查 // 因为 vitess 的 parser 对于 DDL 语法支持不好,通过在测试环境执行辅助进行语法检查
if common.Config.OnlySyntaxCheck && vEnv.BuildVirtualEnv(rEnv, sql) { if common.Config.OnlySyntaxCheck && vEnv.BuildVirtualEnv(rEnv, sql) {
syntaxErr = vEnv.Error syntaxErr = vEnv.Error
} }
...@@ -248,7 +248,7 @@ func main() { ...@@ -248,7 +248,7 @@ func main() {
if !common.Config.DryRun { if !common.Config.DryRun {
os.Exit(1) os.Exit(1)
} }
// vitess 语法检查给出的建议ERR.000 // vitess 语法检查给出的建议 ERR.000
if common.Config.TestDSN.Disable { if common.Config.TestDSN.Disable {
mysqlSuggest["ERR.000"] = advisor.RuleMySQLError("ERR.000", syntaxErr) mysqlSuggest["ERR.000"] = advisor.RuleMySQLError("ERR.000", syntaxErr)
} }
...@@ -277,14 +277,14 @@ func main() { ...@@ -277,14 +277,14 @@ func main() {
// +++++++++++++++++++++索引优化建议[开始]+++++++++++++++++++++++{ // +++++++++++++++++++++索引优化建议[开始]+++++++++++++++++++++++{
// 如果配置了索引建议过滤规则,不进行索引优化建议 // 如果配置了索引建议过滤规则,不进行索引优化建议
// 在配置文件ignore-rules中添加 'IDX.*'即可屏蔽索引优化建议 // 在配置文件 ignore-rules 中添加 'IDX.*' 即可屏蔽索引优化建议
common.Log.Debug("start of index advisor Query: %s", q.Query) common.Log.Debug("start of index advisor Query: %s", q.Query)
if !advisor.IsIgnoreRule("IDX.") { if !advisor.IsIgnoreRule("IDX.") {
if vEnv.BuildVirtualEnv(rEnv, q.Query) { if vEnv.BuildVirtualEnv(rEnv, q.Query) {
idxAdvisor, err := advisor.NewAdvisor(vEnv, *rEnv, *q) idxAdvisor, err := advisor.NewAdvisor(vEnv, *rEnv, *q)
if err != nil || (idxAdvisor == nil && vEnv.Error == nil) { if err != nil || (idxAdvisor == nil && vEnv.Error == nil) {
if idxAdvisor == nil { if idxAdvisor == nil {
// 如果SQL是DDL语句,则返回的idxAdvisor为nil,可以忽略不处理 // 如果 SQL 是 DDL 语句,则返回的 idxAdvisor 为 nil,可以忽略不处理
// TODO alter table add index 语句检查索引是否已经存在 // TODO alter table add index 语句检查索引是否已经存在
common.Log.Debug("idxAdvisor by pass Query: %s", q.Query) common.Log.Debug("idxAdvisor by pass Query: %s", q.Query)
} else { } else {
...@@ -311,7 +311,7 @@ func main() { ...@@ -311,7 +311,7 @@ func main() {
Case: sql, Case: sql,
} }
default: default:
// vEnv.VEnvBuild阶段给出的ERROR是ERR.001 // vEnv.VEnvBuild 阶段给出的 ERROR 是 ERR.001
mysqlSuggest["ERR.001"] = advisor.RuleMySQLError("ERR.001", vEnv.Error) mysqlSuggest["ERR.001"] = advisor.RuleMySQLError("ERR.001", vEnv.Error)
common.Log.Error("BuildVirtualEnv DDL Execute Error : %v", vEnv.Error) common.Log.Error("BuildVirtualEnv DDL Execute Error : %v", vEnv.Error)
} }
...@@ -324,30 +324,30 @@ func main() { ...@@ -324,30 +324,30 @@ func main() {
common.Log.Debug("end of index advisor Query: %s", q.Query) common.Log.Debug("end of index advisor Query: %s", q.Query)
// +++++++++++++++++++++索引优化建议[结束]+++++++++++++++++++++++} // +++++++++++++++++++++索引优化建议[结束]+++++++++++++++++++++++}
// +++++++++++++++++++++EXPLAIN建议[开始]+++++++++++++++++++++++{ // +++++++++++++++++++++EXPLAIN 建议[开始]+++++++++++++++++++++++{
// 如果未配置Online或Test无法给Explain建议 // 如果未配置 Online 或 Test 无法给 Explain 建议
common.Log.Debug("start of explain Query: %s", q.Query) common.Log.Debug("start of explain Query: %s", q.Query)
if !common.Config.OnlineDSN.Disable && !common.Config.TestDSN.Disable { if !common.Config.OnlineDSN.Disable && !common.Config.TestDSN.Disable {
// 因为EXPLAIN依赖数据库环境,所以把这段逻辑放在启发式建议和索引建议后面 // 因为 EXPLAIN 依赖数据库环境,所以把这段逻辑放在启发式建议和索引建议后面
if common.Config.Explain { if common.Config.Explain {
// 执行EXPLAIN // 执行 EXPLAIN
explainInfo, err := rEnv.Explain(q.Query, explainInfo, err := rEnv.Explain(q.Query,
database.ExplainType[common.Config.ExplainType], database.ExplainType[common.Config.ExplainType],
database.ExplainFormatType[common.Config.ExplainFormat]) database.ExplainFormatType[common.Config.ExplainFormat])
if err != nil { if err != nil {
// 线上环境执行失败才到测试环境EXPLAIN,比如在用户提供建表语句及查询语句的场景 // 线上环境执行失败才到测试环境 EXPLAIN,比如在用户提供建表语句及查询语句的场景
common.Log.Warn("rEnv.Explain Warn: %v", err) common.Log.Warn("rEnv.Explain Warn: %v", err)
explainInfo, err = vEnv.Explain(q.Query, explainInfo, err = vEnv.Explain(q.Query,
database.ExplainType[common.Config.ExplainType], database.ExplainType[common.Config.ExplainType],
database.ExplainFormatType[common.Config.ExplainFormat]) database.ExplainFormatType[common.Config.ExplainFormat])
if err != nil { if err != nil {
// EXPLAIN阶段给出的ERROR是ERR.002 // EXPLAIN 阶段给出的 ERROR 是 ERR.002
mysqlSuggest["ERR.002"] = advisor.RuleMySQLError("ERR.002", err) mysqlSuggest["ERR.002"] = advisor.RuleMySQLError("ERR.002", err)
common.Log.Error("vEnv.Explain Error: %v", err) common.Log.Error("vEnv.Explain Error: %v", err)
continue continue
} }
} }
// 分析EXPLAIN结果 // 分析 EXPLAIN 结果
if explainInfo != nil { if explainInfo != nil {
expSuggest = advisor.ExplainAdvisor(explainInfo) expSuggest = advisor.ExplainAdvisor(explainInfo)
} else { } else {
...@@ -356,9 +356,9 @@ func main() { ...@@ -356,9 +356,9 @@ func main() {
} }
} }
common.Log.Debug("end of explain Query: %s", q.Query) common.Log.Debug("end of explain Query: %s", q.Query)
// +++++++++++++++++++++EXPLAIN建议[结束]+++++++++++++++++++++++} // +++++++++++++++++++++ EXPLAIN 建议[结束]+++++++++++++++++++++++}
// +++++++++++++++++++++Profiling[开始]+++++++++++++++++++++++++{ // +++++++++++++++++++++ Profiling [开始]+++++++++++++++++++++++++{
common.Log.Debug("start of profiling Query: %s", q.Query) common.Log.Debug("start of profiling Query: %s", q.Query)
if common.Config.Profiling { if common.Config.Profiling {
res, err := vEnv.Profiling(q.Query) res, err := vEnv.Profiling(q.Query)
...@@ -373,9 +373,9 @@ func main() { ...@@ -373,9 +373,9 @@ func main() {
} }
} }
common.Log.Debug("end of profiling Query: %s", q.Query) common.Log.Debug("end of profiling Query: %s", q.Query)
// +++++++++++++++++++++Profiling[结束]++++++++++++++++++++++++++} // +++++++++++++++++++++ Profiling [结束]++++++++++++++++++++++++++}
// +++++++++++++++++++++Trace [开始]+++++++++++++++++++++++++{ // +++++++++++++++++++++ Trace [开始]+++++++++++++++++++++++++{
common.Log.Debug("start of trace Query: %s", q.Query) common.Log.Debug("start of trace Query: %s", q.Query)
if common.Config.Trace { if common.Config.Trace {
res, err := vEnv.Trace(q.Query) res, err := vEnv.Trace(q.Query)
...@@ -392,14 +392,14 @@ func main() { ...@@ -392,14 +392,14 @@ func main() {
common.Log.Debug("end of trace Query: %s", q.Query) common.Log.Debug("end of trace Query: %s", q.Query)
// +++++++++++++++++++++Trace [结束]++++++++++++++++++++++++++} // +++++++++++++++++++++Trace [结束]++++++++++++++++++++++++++}
// +++++++++++++++++++++SQL重写[开始]+++++++++++++++++++++++++{ // +++++++++++++++++++++SQL 重写[开始]+++++++++++++++++++++++++{
common.Log.Debug("start of rewrite Query: %s", q.Query) common.Log.Debug("start of rewrite Query: %s", q.Query)
if common.Config.ReportType == "rewrite" { if common.Config.ReportType == "rewrite" {
if strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "create") || if strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "create") ||
strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "alter") || strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "alter") ||
strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "rename") { strings.HasPrefix(strings.TrimSpace(strings.ToLower(sql)), "rename") {
// 依赖上下文件的SQL重写,如:多条ALTER SQL合并 // 依赖上下文件的 SQL 重写,如:多条 ALTER SQL 合并
// vitess对DDL语法的支持不好,大部分DDL会语法解析出错,但即使出错了还是会生成一个stmt而且里面的db.table还是准确的。 // vitess 对 DDL 语法的支持不好,大部分 DDL 会语法解析出错,但即使出错了还是会生成一个 stmt 而且里面的 db.table 还是准确的。
alterSqls = append(alterSqls, sql) alterSqls = append(alterSqls, sql)
alterTbl := ast.AlterAffectTable(stmt) alterTbl := ast.AlterAffectTable(stmt)
...@@ -412,25 +412,25 @@ func main() { ...@@ -412,25 +412,25 @@ func main() {
} }
} }
} else { } else {
// 其他不依赖上下文件的SQL重写 // 其他不依赖上下文件的 SQL 重写
rw := ast.NewRewrite(sql) rw := ast.NewRewrite(sql)
if rw == nil { if rw == nil {
// 都到这一步了sql不会语法不正确,因此rw一般不会为nil // 都到这一步了 sql 不会语法不正确,因此 rw 一般不会为 nil
common.Log.Critical("NewRewrite nil point error, SQL: %s", sql) common.Log.Critical("NewRewrite nil point error, SQL: %s", sql)
os.Exit(1) os.Exit(1)
} }
// SQL转写需要的源信息采集,如果没有配置环境则只做有限改写 // SQL 转写需要的源信息采集,如果没有配置环境则只做有限改写
meta := ast.GetMeta(rw.Stmt, nil) meta := ast.GetMeta(rw.Stmt, nil)
rw.Columns = vEnv.GenTableColumns(meta) rw.Columns = vEnv.GenTableColumns(meta)
// 执行定义好的SQL重写规则 // 执行定义好的 SQL 重写规则
rw.Rewrite() rw.Rewrite()
fmt.Println(strings.TrimSpace(rw.NewSQL)) fmt.Println(strings.TrimSpace(rw.NewSQL))
} }
} }
common.Log.Debug("end of rewrite Query: %s", q.Query) common.Log.Debug("end of rewrite Query: %s", q.Query)
// +++++++++++++++++++++SQL重写[结束]++++++++++++++++++++++++++} // +++++++++++++++++++++ SQL 重写[结束]++++++++++++++++++++++++++}
// +++++++++++++++++++++打印单条SQL优化建议[开始]++++++++++++++++++++++++++{ // +++++++++++++++++++++打印单条 SQL 优化建议[开始]++++++++++++++++++++++++++{
common.Log.Debug("start of print suggestions, Query: %s", q.Query) common.Log.Debug("start of print suggestions, Query: %s", q.Query)
sug, str := advisor.FormatSuggest(q.Query, common.Config.ReportType, heuristicSuggest, idxSuggest, expSuggest, proSuggest, traceSuggest, mysqlSuggest) sug, str := advisor.FormatSuggest(q.Query, common.Config.ReportType, heuristicSuggest, idxSuggest, expSuggest, proSuggest, traceSuggest, mysqlSuggest)
suggestMerged[id] = sug suggestMerged[id] = sug
...@@ -462,10 +462,10 @@ func main() { ...@@ -462,10 +462,10 @@ func main() {
fmt.Println(str) fmt.Println(str)
} }
common.Log.Debug("end of print suggestions, Query: %s", q.Query) common.Log.Debug("end of print suggestions, Query: %s", q.Query)
// +++++++++++++++++++++打印单条SQL优化建议[结束]++++++++++++++++++++++++++} // +++++++++++++++++++++打印单条 SQL 优化建议[结束]++++++++++++++++++++++++++}
} }
// 同一张表的多条ALTER语句合并为一条 // 同一张表的多条 ALTER 语句合并为一条
if ast.RewriteRuleMatch("mergealter") { if ast.RewriteRuleMatch("mergealter") {
for _, v := range ast.MergeAlterTables(alterSqls...) { for _, v := range ast.MergeAlterTables(alterSqls...) {
fmt.Println(strings.TrimSpace(v)) fmt.Println(strings.TrimSpace(v))
...@@ -473,7 +473,7 @@ func main() { ...@@ -473,7 +473,7 @@ func main() {
return return
} }
// 以JSON格式化输出 // 以 JSON 格式化输出
if common.Config.ReportType == "json" { if common.Config.ReportType == "json" {
js, err := json.MarshalIndent(suggestMerged, "", " ") js, err := json.MarshalIndent(suggestMerged, "", " ")
if err == nil { if err == nil {
......
## 常见问题 # 常见问题
### 软件依赖 ## 软件依赖
* [git](https://git-scm.co) 项目代码管理工具 * [git](https://git-scm.co) 项目代码管理工具
* [go](https://golang.org/) 源码编译依赖 * [go](https://golang.org/) 源码编译依赖
* [govendor](https://github.com/kardianos/govendor) 管理第三方包 * [govendor](https://github.com/kardianos/govendor) 管理第三方包
* [docker](https://www.docker.com) 主要用于构建测试环境 * [docker](https://www.docker.com) 主要用于构建测试环境
* [mysql](https://www.mysql.com/) 测试时用来连接测试环境 * [mysql](https://www.mysql.com/) 测试时用来连接测试环境
* [retool](https://github.com/twitchtv/retool): 管理测试开发工具,首次安装耗时会比较长,如:`gometalinter.v2`, `revive`, `golangci-lint` * [retool](https://github.com/twitchtv/retool): 管理测试开发工具,首次安装耗时会比较长,如: `gometalinter.v2`, `revive`, `golangci-lint`
### 命令行参数`test-dsn`, `online-dsn`中包含特殊字符怎么办? ## 命令行参数 `test-dsn`, `online-dsn` 中包含特殊字符怎么办?
如果`test-dsn``online-dsn`中包含':', '@', '/', '!'等特殊字符建议在配置文件中配置相关信息,配置文件为YAML格式,需要遵守YAML格式的要求规范。 如果 `test-dsn``online-dsn` 中包含':', '@', '/', '!'等特殊字符建议在配置文件中配置相关信息,配置文件为YAML格式,需要遵守YAML格式的要求规范。
### Windows环境下双击`soar.windows-amd64`文件无反应。 ## Windows环境下双击`soar.windows-amd64`文件无反应。
`soar`是命令行工具,不是图形化桌面工具,Windows环境需要在`cmd.exe`下以命令行方式运行。使用`soar`前您需要先熟悉Windows命令行使用。 `soar` 是命令行工具,不是图形化桌面工具,Windows环境需要在 `cmd.exe` 下以命令行方式运行。使用 `soar` 前您需要先熟悉Windows命令行使用。
### 提示语法错误 ## Windows 用户的引号问题
![windows_quote](https://raw.githubusercontent.com/XiaoMi/soar/master/doc/images/windows_quote.png)
从上图可以看出 Windows 环境下引号(单引号或双引号)也成为了SQL的一部分传递给 soar 进行分析。因此 Windows 环境下使用如下方式读取 SQL 来解决 Windows 的引号问题。
```bash
type query.sql | soar.windows-amd64
```
## 提示语法错误
* 请检查SQL语句中是否出现了不配对的引号,如 `, ", ' * 请检查SQL语句中是否出现了不配对的引号,如 `, ", '
### 输出结果返回慢 ## 输出结果返回慢
* 如果配置了online-dsn或test-dsn SOAR会请求这些数据库以支持更多的功能,这时评审一条SQL就会耗时变长。 * 如果配置了 online-dsn 或 test-dsn SOAR 会请求这些数据库以支持更多的功能,这时评审一条SQL就会耗时变长。
* 如果又开启了`-sampling=true`的话会将线上的数据导入到测试环境,数据采样也会消耗一些时间。 * 如果又开启了 `-sampling=true` 的话会将线上的数据导入到测试环境,数据采样也会消耗一些时间。
## 如何搭建测试环境 ## 如何搭建测试环境
...@@ -47,7 +57,7 @@ GRANT ALL ON *.* TO root@'hostname'; ...@@ -47,7 +57,7 @@ GRANT ALL ON *.* TO root@'hostname';
如属更新vitess仓库可以使用如下命令。 如属更新vitess仓库可以使用如下命令。
```bash ```bash
$ make vitess make vitess
``` ```
## 生成报告并发邮件 ## 生成报告并发邮件
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册