提交 461b6899 编写于 作者: martianzhang's avatar martianzhang

extract config check into initConfig

上级 d622a265
...@@ -58,7 +58,7 @@ func checkExplainSelectType(exp *database.ExplainInfo) { ...@@ -58,7 +58,7 @@ func checkExplainSelectType(exp *database.ExplainInfo) {
if exp.ExplainFormat == database.JSONFormatExplain { if exp.ExplainFormat == database.JSONFormatExplain {
// TODO // TODO
// JSON形式遍历分析不方便,转成Row格式也没有SelectType暂不处理 // JSON 形式遍历分析不方便,转成 Row 格式也没有 SelectType 暂不处理
return return
} }
for _, v := range common.Config.ExplainWarnSelectType { for _, v := range common.Config.ExplainWarnSelectType {
......
...@@ -1446,7 +1446,7 @@ func (q *Query4Audit) RuleSubqueryDepth() Rule { ...@@ -1446,7 +1446,7 @@ func (q *Query4Audit) RuleSubqueryDepth() Rule {
} }
// RuleSubQueryLimit SUB.005 // RuleSubQueryLimit SUB.005
// 只有IN的SUBQUERY限制了LIMIT,FROM子句中的SUBQUERY并未限制LIMIT // 只有 IN 的 SUBQUERY 限制了 LIMIT, FROM 子句中的 SUBQUERY 并未限制 LIMIT
func (q *Query4Audit) RuleSubQueryLimit() Rule { func (q *Query4Audit) RuleSubQueryLimit() Rule {
var rule = q.RuleOK() var rule = q.RuleOK()
err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
...@@ -1890,7 +1890,7 @@ func (idxAdv *IndexAdvisor) RuleUpdatePrimaryKey() Rule { ...@@ -1890,7 +1890,7 @@ func (idxAdv *IndexAdvisor) RuleUpdatePrimaryKey() Rule {
err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
switch node.(type) { switch node.(type) {
case *sqlparser.UpdateExpr: case *sqlparser.UpdateExpr:
// 获取set操作的全部column // 获取 set 操作的全部 column
setColumns = append(setColumns, ast.FindAllCols(node)...) setColumns = append(setColumns, ast.FindAllCols(node)...)
} }
return true, nil return true, nil
...@@ -2820,7 +2820,7 @@ func (q *Query4Audit) RuleIntPrecision() Rule { ...@@ -2820,7 +2820,7 @@ func (q *Query4Audit) RuleIntPrecision() Rule {
switch col.Tp.Tp { switch col.Tp.Tp {
case mysql.TypeLong: case mysql.TypeLong:
if (col.Tp.Flen < 10 || col.Tp.Flen > 11) && col.Tp.Flen > 0 { if (col.Tp.Flen < 10 || col.Tp.Flen > 11) && col.Tp.Flen > 0 {
// 有些语言ORM框架会生成int(11),有些语言的框架生成int(10) // 有些语言 ORM 框架会生成 int(11),有些语言的框架生成 int(10)
rule = HeuristicRules["COL.016"] rule = HeuristicRules["COL.016"]
break break
} }
...@@ -2840,7 +2840,7 @@ func (q *Query4Audit) RuleIntPrecision() Rule { ...@@ -2840,7 +2840,7 @@ func (q *Query4Audit) RuleIntPrecision() Rule {
switch col.Tp.Tp { switch col.Tp.Tp {
case mysql.TypeLong: case mysql.TypeLong:
if (col.Tp.Flen < 10 || col.Tp.Flen > 11) && col.Tp.Flen > 0 { if (col.Tp.Flen < 10 || col.Tp.Flen > 11) && col.Tp.Flen > 0 {
// 有些语言ORM框架会生成int(11),有些语言的框架生成int(10) // 有些语言 ORM 框架会生成 int(11),有些语言的框架生成 int(10)
rule = HeuristicRules["COL.016"] rule = HeuristicRules["COL.016"]
break break
} }
......
...@@ -48,7 +48,7 @@ type IndexInfo struct { ...@@ -48,7 +48,7 @@ type IndexInfo struct {
Name string `json:"name"` // 索引名称 Name string `json:"name"` // 索引名称
Database string `json:"database"` // 数据库名 Database string `json:"database"` // 数据库名
Table string `json:"table"` // 表名 Table string `json:"table"` // 表名
DDL string `json:"ddl"` // ALTER, CREATE等类型的DDL语句 DDL string `json:"ddl"` // ALTER, CREATE 等类型的 DDL 语句
ColumnDetails []*common.Column `json:"column_details"` // 列详情 ColumnDetails []*common.Column `json:"column_details"` // 列详情
} }
...@@ -96,7 +96,7 @@ func NewAdvisor(env *env.VirtualEnv, rEnv database.Connector, q Query4Audit) (*I ...@@ -96,7 +96,7 @@ func NewAdvisor(env *env.VirtualEnv, rEnv database.Connector, q Query4Audit) (*I
dbRef = rEnv.Database dbRef = rEnv.Database
} }
// DDL在Env初始化的时候已经执行过了 // DDL 在 Env 初始化的时候已经执行过了
if _, ok := env.TableMap[dbRef]; !ok { if _, ok := env.TableMap[dbRef]; !ok {
env.TableMap[dbRef] = make(map[string]string) env.TableMap[dbRef] = make(map[string]string)
} }
...@@ -279,15 +279,15 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises { ...@@ -279,15 +279,15 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises {
if len(idxAdv.whereINEQ) > 0 { if len(idxAdv.whereINEQ) > 0 {
mergeIndex(indexList, idxAdv.whereINEQ[0]) mergeIndex(indexList, idxAdv.whereINEQ[0])
} }
// 有WHERE条件,但WHERE条件未能给出索引建议就不能再加GROUP BY和ORDER BY建议了 // 有WHERE条件,但 WHERE 条件未能给出索引建议就不能再加 GROUP BY 和 ORDER BY 建议了
if len(ignore) == 0 { if len(ignore) == 0 {
// 没有非等值查询条件时可以再为GroupBy和OrderBy添加索引 // 没有非等值查询条件时可以再为 GroupBy 和 OrderBy 添加索引
for _, index := range idxAdv.groupBy { for _, index := range idxAdv.groupBy {
mergeIndex(indexList, index) mergeIndex(indexList, index)
} }
// OrderBy // OrderBy
// 没有GroupBy时可以为OrderBy加索引 // 没有 GroupBy 时可以为 OrderBy 加索引
if len(idxAdv.groupBy) == 0 { if len(idxAdv.groupBy) == 0 {
for _, index := range idxAdv.orderBy { for _, index := range idxAdv.orderBy {
mergeIndex(indexList, index) mergeIndex(indexList, index)
...@@ -295,14 +295,14 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises { ...@@ -295,14 +295,14 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises {
} }
} }
} else { } else {
// 未指定Where条件的,只需要GroupBy和OrderBy的索引建议 // 未指定 Where 条件的,只需要 GroupBy 和 OrderBy 的索引建议
for _, index := range idxAdv.groupBy { for _, index := range idxAdv.groupBy {
mergeIndex(indexList, index) mergeIndex(indexList, index)
} }
// OrderBy // OrderBy
// 没有GroupBy时可以为OrderBy加索引 // 没有GroupBy 时可以为 OrderBy 加索引
// 没有where条件时OrderBy的索引仅能够在索引覆盖的情况下被使用 // 没有 where 条件时 OrderBy 的索引仅能够在索引覆盖的情况下被使用
// if len(idxAdv.groupBy) == 0 { // if len(idxAdv.groupBy) == 0 {
// for _, index := range idxAdv.orderBy { // for _, index := range idxAdv.orderBy {
...@@ -329,8 +329,8 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises { ...@@ -329,8 +329,8 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises {
indexes = mergeAdvices(indexes, idxAdv.buildJoinIndex(joinTableMeta)...) indexes = mergeAdvices(indexes, idxAdv.buildJoinIndex(joinTableMeta)...)
if common.Config.TestDSN.Disable || common.Config.OnlineDSN.Disable { if common.Config.TestDSN.Disable || common.Config.OnlineDSN.Disable {
// 无env环境下只提供单列索引,无法确定table时不给予优化建议 // 无 env 环境下只提供单列索引,无法确定 table 时不给予优化建议
// 仅有table信息时给出的建议不包含DB信息 // 仅有 table 信息时给出的建议不包含 DB 信息
indexes = mergeAdvices(indexes, idxAdv.buildIndexWithNoEnv(indexList)...) indexes = mergeAdvices(indexes, idxAdv.buildIndexWithNoEnv(indexList)...)
} else { } else {
// 给出尽可能详细的索引建议 // 给出尽可能详细的索引建议
...@@ -339,16 +339,16 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises { ...@@ -339,16 +339,16 @@ func (idxAdv *IndexAdvisor) IndexAdvise() IndexAdvises {
indexes = mergeAdvices(indexes, subQueryAdvises...) indexes = mergeAdvices(indexes, subQueryAdvises...)
// 在开启env的情况下,检查数据库版本,字段类型,索引总长度 // 在开启 env 的情况下,检查数据库版本,字段类型,索引总长度
indexes = idxAdv.idxColsTypeCheck(indexes) indexes = idxAdv.idxColsTypeCheck(indexes)
// 在开启env的情况下,会对索引进行检查,对全索引进行过滤 // 在开启 env 的情况下,会对索引进行检查,对全索引进行过滤
// 在前几步都不会对idx生成DDL语句,DDL语句在这里生成 // 在前几步都不会对 idx 生成 DDL 语句,DDL语句在这里生成
return idxAdv.mergeIndexes(indexes) return idxAdv.mergeIndexes(indexes)
} }
// idxColsTypeCheck 对超长的字段添加前缀索引,剔除无法添索引字段的列 // idxColsTypeCheck 对超长的字段添加前缀索引,剔除无法添索引字段的列
// TODO 暂不支持fulltext索引, // TODO: 暂不支持 fulltext 索引,
func (idxAdv *IndexAdvisor) idxColsTypeCheck(idxList []IndexInfo) []IndexInfo { func (idxAdv *IndexAdvisor) idxColsTypeCheck(idxList []IndexInfo) []IndexInfo {
if common.Config.TestDSN.Disable { if common.Config.TestDSN.Disable {
return rmSelfDupIndex(idxList) return rmSelfDupIndex(idxList)
...@@ -363,7 +363,7 @@ func (idxAdv *IndexAdvisor) idxColsTypeCheck(idxList []IndexInfo) []IndexInfo { ...@@ -363,7 +363,7 @@ func (idxAdv *IndexAdvisor) idxColsTypeCheck(idxList []IndexInfo) []IndexInfo {
idxBytesTotal := 0 idxBytesTotal := 0
isOverFlow := false isOverFlow := false
for _, col := range idx.ColumnDetails { for _, col := range idx.ColumnDetails {
// 获取字段bytes // 获取字段 bytes
bytes := col.GetDataBytes(common.Config.OnlineDSN.Version) bytes := col.GetDataBytes(common.Config.OnlineDSN.Version)
tmpCol := col.Name tmpCol := col.Name
overFlow := 0 overFlow := 0
...@@ -474,7 +474,7 @@ func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo { ...@@ -474,7 +474,7 @@ func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo {
var indexes []IndexInfo var indexes []IndexInfo
for _, idx := range idxList { for _, idx := range idxList {
// 将DB替换成vEnv中的数据库名称 // 将 DB 替换成 vEnv 中的数据库名称
dbInVEnv := idx.Database dbInVEnv := idx.Database
if _, ok := idxAdv.vEnv.DBRef[idx.Database]; ok { if _, ok := idxAdv.vEnv.DBRef[idx.Database]; ok {
dbInVEnv = idxAdv.vEnv.DBRef[idx.Database] dbInVEnv = idxAdv.vEnv.DBRef[idx.Database]
...@@ -503,7 +503,7 @@ func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo { ...@@ -503,7 +503,7 @@ func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo {
var cols []string var cols []string
var colsDetail []*common.Column var colsDetail []*common.Column
// 把已经存在的key摘出来遍历一遍对比是否是包含关系 // 把已经存在的 key 摘出来遍历一遍对比是否是包含关系
for _, col := range indexMeta.FindIndex(database.IndexKeyName, existedIdx.KeyName) { for _, col := range indexMeta.FindIndex(database.IndexKeyName, existedIdx.KeyName) {
cols = append(cols, col.ColumnName) cols = append(cols, col.ColumnName)
colsDetail = append(colsDetail, &common.Column{ colsDetail = append(colsDetail, &common.Column{
...@@ -532,7 +532,7 @@ func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo { ...@@ -532,7 +532,7 @@ func (idxAdv *IndexAdvisor) mergeIndexes(idxList []IndexInfo) []IndexInfo {
} }
// 库、表、列名需要用反撇转义 // 库、表、列名需要用反撇转义
// TODO 关于外键索引去重的优雅解决方案 // TODO: 关于外键索引去重的优雅解决方案
if !isConstraint { if !isConstraint {
if common.Config.AllowDropIndex { if common.Config.AllowDropIndex {
alterSQL := fmt.Sprintf("alter table `%s`.`%s` drop index `%s`", idx.Database, idx.Table, idxName) alterSQL := fmt.Sprintf("alter table `%s`.`%s` drop index `%s`", idx.Database, idx.Table, idxName)
...@@ -736,12 +736,12 @@ func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *e ...@@ -736,12 +736,12 @@ func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *e
return cols return cols
} }
// 从Ast中拿到DBStructure,包含所有表的相关信息 // 从 Ast 中拿到 DBStructure,包含所有表的相关信息
dbs := ast.GetMeta(stmt, nil) dbs := ast.GetMeta(stmt, nil)
// 此处生成的meta信息中不应该含有""db的信息,若DB为空则认为是已传入的db为默认db并进行信息补全 // 此处生成的 meta 信息中不应该含有""db的信息,若 DB 为空则认为是已传入的 db 为默认 db 并进行信息补全
// BUG Fix: // BUG Fix:
// 修补dbs中空DB的导致后续补全列信息时无法获取正确table名称的问题 // 修补 dbs 中空 DB 的导致后续补全列信息时无法获取正确 table 名称的问题
if _, ok := dbs[""]; ok { if _, ok := dbs[""]; ok {
dbs[env.Database] = dbs[""] dbs[env.Database] = dbs[""]
delete(dbs, "") delete(dbs, "")
...@@ -829,7 +829,7 @@ func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *e ...@@ -829,7 +829,7 @@ func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *e
// 将已经获取到正确表信息的列信息带入到env中,利用show columns where table 获取库表信息 // 将已经获取到正确表信息的列信息带入到env中,利用show columns where table 获取库表信息
// 此出会传入之前从ast中,该 db 下获取的所有表来作为where限定条件, // 此出会传入之前从ast中,该 db 下获取的所有表来作为where限定条件,
// 防止与SQL无关的库表信息干扰准确性 // 防止与SQL无关的库表信息干扰准确性
// 此处传入的是测试环境,DB是经过变换的,所以在寻找列名的时候需要将DB名称转换成测试环境中经过hash的DB名称 // 此处传入的是测试环境,DB 是经过变换的,所以在寻找列名的时候需要将 DB 名称转换成测试环境中经过 hash 的 DB 名称
// 不然会找不到col的信息 // 不然会找不到col的信息
realCols, err := env.FindColumn(col.Name, env.DBHash(db), dbs.Tables(db)...) realCols, err := env.FindColumn(col.Name, env.DBHash(db), dbs.Tables(db)...)
if err != nil { if err != nil {
...@@ -840,7 +840,7 @@ func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *e ...@@ -840,7 +840,7 @@ func CompleteColumnsInfo(stmt sqlparser.Statement, cols []*common.Column, env *e
// 对比 column 信息中的表名与从 env 中获取的库表名的一致性 // 对比 column 信息中的表名与从 env 中获取的库表名的一致性
for _, realCol := range realCols { for _, realCol := range realCols {
if col.Name == realCol.Name { if col.Name == realCol.Name {
// 如果查询到了列名一致,但从ast中获取的列的前缀与env中的表信息不符 // 如果查询到了列名一致,但从 ast 中获取的列的前缀与 env 中的表信息不符
// 1.存在一个同名列,但不同表,该情况下忽略 // 1.存在一个同名列,但不同表,该情况下忽略
// 2.存在一个未正确转换的别名(如表名为),该情况下修正,大概率是正确的 // 2.存在一个未正确转换的别名(如表名为),该情况下修正,大概率是正确的
if col.Table != "" && col.Table != realCol.Table { if col.Table != "" && col.Table != realCol.Table {
...@@ -897,7 +897,7 @@ func (idxAdv *IndexAdvisor) calcCardinality(cols []*common.Column) []*common.Col ...@@ -897,7 +897,7 @@ func (idxAdv *IndexAdvisor) calcCardinality(cols []*common.Column) []*common.Col
continue continue
} }
// 将获取的索引信息以db.tb维度组织到IndexMeta // 将获取的索引信息以db.tb 维度组织到 IndexMeta
idxAdv.IndexMeta[realDB][col.Table] = indexInfo idxAdv.IndexMeta[realDB][col.Table] = indexInfo
} }
...@@ -1039,7 +1039,7 @@ func DuplicateKeyChecker(conn *database.Connector, databases ...string) map[stri ...@@ -1039,7 +1039,7 @@ func DuplicateKeyChecker(conn *database.Connector, databases ...string) map[stri
} }
} }
// 不指定DB的时候检查online dsn中的DB // 不指定 DB 的时候检查 online dsn 中的 DB
if len(databases) == 0 { if len(databases) == 0 {
databases = append(databases, tmpOnline.Database) databases = append(databases, tmpOnline.Database)
} }
......
...@@ -989,7 +989,7 @@ func init() { ...@@ -989,7 +989,7 @@ func init() {
Case: "SELECT DISTINCT c.c_id, c.c_name FROM c,e WHERE e.c_id = c.c_id", Case: "SELECT DISTINCT c.c_id, c.c_name FROM c,e WHERE e.c_id = c.c_id",
Func: (*Query4Audit).RuleDistinctJoinUsage, Func: (*Query4Audit).RuleDistinctJoinUsage,
}, },
// TODO: 5.6有了semi join还要把in转成exists么? // TODO: 5.6有了semi join 还要把 in 转成e xists 么?
// Use EXISTS instead of IN to check existence of data. // Use EXISTS instead of IN to check existence of data.
// http://www.winwire.com/25-tips-to-improve-sql-query-performance/ // http://www.winwire.com/25-tips-to-improve-sql-query-performance/
"SUB.004": { "SUB.004": {
......
...@@ -38,6 +38,7 @@ import ( ...@@ -38,6 +38,7 @@ import (
func main() { func main() {
// 全局变量 // 全局变量
var err error
var sql string // 单条评审指定的 sql 或 explain var sql string // 单条评审指定的 sql 或 explain
sqlCounter := 1 // SQL 计数器 sqlCounter := 1 // SQL 计数器
lineCounter := 1 // 行计数器 lineCounter := 1 // 行计数器
...@@ -45,15 +46,8 @@ func main() { ...@@ -45,15 +46,8 @@ func main() {
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()
if err != nil {
panic(err)
}
common.BaseDir = filepath.Dir(ex) // binary 文件所在路径
// 配置文件&命令行参数解析 // 配置文件&命令行参数解析
err = common.ParseConfig(common.ArgConfig()) initConfig()
common.LogIfWarn(err, "")
// 打印支持启发式建议 // 打印支持启发式建议
if common.Config.ListHeuristicRules { if common.Config.ListHeuristicRules {
...@@ -496,6 +490,33 @@ func main() { ...@@ -496,6 +490,33 @@ func main() {
} }
} }
func initConfig() {
// 更新 binary 文件所在路径为 BaseDir
ex, err := os.Executable()
if err != nil {
panic(err)
}
common.BaseDir = filepath.Dir(ex)
for i, c := range os.Args {
// 如果指定了 -config, 它必须是第一个参数
if strings.HasPrefix(c, "-config") && i != 1 {
fmt.Println("-config must be the first arg")
os.Exit(1)
}
// 等号两边请不要加空格
if c == "=" {
// -config = soar.yaml not support
fmt.Println("wrong format, no space between '=', eg: -config=soar.yaml")
os.Exit(1)
}
}
// 加载配置文件,处理命令行参数
err = common.ParseConfig(common.ArgConfig())
common.LogIfWarn(err, "")
}
func shutdown(vEnv *env.VirtualEnv, rEnv *database.Connector) { func shutdown(vEnv *env.VirtualEnv, rEnv *database.Connector) {
if common.Config.DropTestTemporary { if common.Config.DropTestTemporary {
vEnv.CleanUp() vEnv.CleanUp()
......
...@@ -78,18 +78,18 @@ type Configration struct { ...@@ -78,18 +78,18 @@ type Configration struct {
RewriteRules []string `yaml:"rewrite-rules"` // 生效的重写规则 RewriteRules []string `yaml:"rewrite-rules"` // 生效的重写规则
BlackList string `yaml:"blacklist"` // blacklist 中的 SQL 不会被评审,可以是指纹,也可以是正则 BlackList string `yaml:"blacklist"` // blacklist 中的 SQL 不会被评审,可以是指纹,也可以是正则
MaxJoinTableCount int `yaml:"max-join-table-count"` // 单条 SQL 中 JOIN 表的最大数量 MaxJoinTableCount int `yaml:"max-join-table-count"` // 单条 SQL 中 JOIN 表的最大数量
MaxGroupByColsCount int `yaml:"max-group-by-cols-count"` // 单条SQL中GroupBy包含列的最大数量 MaxGroupByColsCount int `yaml:"max-group-by-cols-count"` // 单条 SQL 中 GroupBy 包含列的最大数量
MaxDistinctCount int `yaml:"max-distinct-count"` // 单条SQL中Distinct的最大数量 MaxDistinctCount int `yaml:"max-distinct-count"` // 单条 SQL 中 Distinct 的最大数量
MaxIdxColsCount int `yaml:"max-index-cols-count"` // 复合索引中包含列的最大数量 MaxIdxColsCount int `yaml:"max-index-cols-count"` // 复合索引中包含列的最大数量
MaxTotalRows int64 `yaml:"max-total-rows"` // 计算散粒度时,当数据行数大于 MaxTotalRows即开启数据库保护模式,散粒度返回结果可信度下降 MaxTotalRows int64 `yaml:"max-total-rows"` // 计算散粒度时,当数据行数大于 MaxTotalRows 即开启数据库保护模式,散粒度返回结果可信度下降
MaxQueryCost int64 `yaml:"max-query-cost"` // last_query_cost 超过该值时将给予警告 MaxQueryCost int64 `yaml:"max-query-cost"` // last_query_cost 超过该值时将给予警告
SpaghettiQueryLength int `yaml:"spaghetti-query-length"` // SQL最大长度警告,超过该长度会给警告 SpaghettiQueryLength int `yaml:"spaghetti-query-length"` // SQL最大长度警告,超过该长度会给警告
AllowDropIndex bool `yaml:"allow-drop-index"` // 允许输出删除重复索引的建议 AllowDropIndex bool `yaml:"allow-drop-index"` // 允许输出删除重复索引的建议
MaxInCount int `yaml:"max-in-count"` // IN()最大数量 MaxInCount int `yaml:"max-in-count"` // IN()最大数量
MaxIdxBytesPerColumn int `yaml:"max-index-bytes-percolumn"` // 索引中单列最大字节数,默认767 MaxIdxBytesPerColumn int `yaml:"max-index-bytes-percolumn"` // 索引中单列最大字节数,默认767
MaxIdxBytes int `yaml:"max-index-bytes"` // 索引总长度限制,默认3072 MaxIdxBytes int `yaml:"max-index-bytes"` // 索引总长度限制,默认3072
TableAllowCharsets []string `yaml:"table-allow-charsets"` // Table允许使用的DEFAULT CHARSET TableAllowCharsets []string `yaml:"table-allow-charsets"` // Table 允许使用的 DEFAULT CHARSET
TableAllowEngines []string `yaml:"table-allow-engines"` // Table允许使用的Engine TableAllowEngines []string `yaml:"table-allow-engines"` // Table 允许使用的 Engine
MaxIdxCount int `yaml:"max-index-count"` // 单张表允许最多索引数 MaxIdxCount int `yaml:"max-index-count"` // 单张表允许最多索引数
MaxColCount int `yaml:"max-column-count"` // 单张表允许最大列数 MaxColCount int `yaml:"max-column-count"` // 单张表允许最大列数
IdxPrefix string `yaml:"index-prefix"` // 普通索引建议使用的前缀 IdxPrefix string `yaml:"index-prefix"` // 普通索引建议使用的前缀
...@@ -98,16 +98,16 @@ type Configration struct { ...@@ -98,16 +98,16 @@ type Configration struct {
MaxVarcharLength int `yaml:"max-varchar-length"` // varchar最大长度 MaxVarcharLength int `yaml:"max-varchar-length"` // varchar最大长度
// ++++++++++++++EXPLAIN检查项+++++++++++++ // ++++++++++++++EXPLAIN检查项+++++++++++++
ExplainSQLReportType string `yaml:"explain-sql-report-type"` // EXPLAIN markdown格式输出SQL样式,支持sample, fingerprint, pretty ExplainSQLReportType string `yaml:"explain-sql-report-type"` // EXPLAIN markdown 格式输出 SQL 样式,支持 sample, fingerprint, pretty 等
ExplainType string `yaml:"explain-type"` // EXPLAIN方式 [traditional, extended, partitions] ExplainType string `yaml:"explain-type"` // EXPLAIN方式 [traditional, extended, partitions]
ExplainFormat string `yaml:"explain-format"` // FORMAT=[json, traditional] ExplainFormat string `yaml:"explain-format"` // FORMAT=[json, traditional]
ExplainWarnSelectType []string `yaml:"explain-warn-select-type"` // 哪些select_type不建议使用 ExplainWarnSelectType []string `yaml:"explain-warn-select-type"` // 哪些 select_type 不建议使用
ExplainWarnAccessType []string `yaml:"explain-warn-access-type"` // 哪些access type不建议使用 ExplainWarnAccessType []string `yaml:"explain-warn-access-type"` // 哪些 access type 不建议使用
ExplainMaxKeyLength int `yaml:"explain-max-keys"` // 最大key_len ExplainMaxKeyLength int `yaml:"explain-max-keys"` // 最大 key_len
ExplainMinPossibleKeys int `yaml:"explain-min-keys"` // 最小possible_keys警告 ExplainMinPossibleKeys int `yaml:"explain-min-keys"` // 最小 possible_keys 警告
ExplainMaxRows int `yaml:"explain-max-rows"` // 最大扫描行数警告 ExplainMaxRows int `yaml:"explain-max-rows"` // 最大扫描行数警告
ExplainWarnExtra []string `yaml:"explain-warn-extra"` // 哪些extra信息会给警告 ExplainWarnExtra []string `yaml:"explain-warn-extra"` // 哪些 extra 信息会给警告
ExplainMaxFiltered float64 `yaml:"explain-max-filtered"` // filtered大于该配置给出警告 ExplainMaxFiltered float64 `yaml:"explain-max-filtered"` // filtered 大于该配置给出警告
ExplainWarnScalability []string `yaml:"explain-warn-scalability"` // 复杂度警告名单 ExplainWarnScalability []string `yaml:"explain-warn-scalability"` // 复杂度警告名单
ShowWarnings bool `yaml:"show-warnings"` // explain extended with show warnings ShowWarnings bool `yaml:"show-warnings"` // explain extended with show warnings
ShowLastQueryCost bool `yaml:"show-last-query-cost"` // switch with show status like 'last_query_cost' ShowLastQueryCost bool `yaml:"show-last-query-cost"` // switch with show status like 'last_query_cost'
...@@ -376,7 +376,7 @@ func version() { ...@@ -376,7 +376,7 @@ func version() {
fmt.Println("GitDirty:", GitDirty) fmt.Println("GitDirty:", GitDirty)
} }
// 因为vitess sqlparser使用了glog中也会使用flag,为了不让用户困扰我们单独写一个usage // 因为vitess sqlparser 使用了 glog 中也会使用 flag,为了不让用户困扰我们单独写一个 usage
func usage() { func usage() {
regPwd := regexp.MustCompile(`:.*@`) regPwd := regexp.MustCompile(`:.*@`)
vitessHelp := []string{ vitessHelp := []string{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册