Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Xiaomi
soar
提交
5619dd32
S
soar
项目概览
Xiaomi
/
soar
大约 2 年 前同步成功
通知
467
Star
8513
Fork
1329
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
soar
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5619dd32
编写于
12月 25, 2018
作者:
martianzhang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
code format add some test case
上级
5c730e2b
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
226 addition
and
244 deletion
+226
-244
advisor/explainer.go
advisor/explainer.go
+16
-68
advisor/index.go
advisor/index.go
+2
-2
advisor/rules_test.go
advisor/rules_test.go
+8
-2
ast/rewrite.go
ast/rewrite.go
+176
-172
cmd/soar/soar_test.go
cmd/soar/soar_test.go
+24
-0
未找到文件。
advisor/explainer.go
浏览文件 @
5619dd32
...
...
@@ -32,20 +32,13 @@ var explainRules map[string]Rule
// [table_name]"suggest text"
var
tablesSuggests
map
[
string
][]
string
/*
var explainIgnoreTables = []string{
"dual",
"",
}
*/
// explain建议的形式
// Item: EXP.XXX
// Severity: L[0-8]
// Summary: full table scan, not use index, full index scan...
// Content: XX TABLE xxx
//
//
checkExplainSelectType
func
checkExplainSelectType
(
exp
*
database
.
ExplainInfo
)
{
// 判断是否跳过不检查
if
len
(
common
.
Config
.
ExplainWarnSelectType
)
==
1
{
...
...
@@ -70,7 +63,7 @@ func checkExplainSelectType(exp *database.ExplainInfo) {
}
}
// 用户可以设置AccessType的建议级别,匹配到的查询会给出建议
//
checkExplainAccessType
用户可以设置AccessType的建议级别,匹配到的查询会给出建议
func
checkExplainAccessType
(
exp
*
database
.
ExplainInfo
)
{
// 判断是否跳过不检查
if
len
(
common
.
Config
.
ExplainWarnAccessType
)
==
1
{
...
...
@@ -95,43 +88,28 @@ func checkExplainAccessType(exp *database.ExplainInfo) {
}
}
// TODO:
/*
// TODO:
func checkExplainPossibleKeys(exp *database.ExplainInfo) {
// 判断是否跳过不检查
if common.Config.ExplainMinPossibleKeys == 0 {
return
}
rows := exp.ExplainRows
if exp.ExplainFormat == database.JSONFormatExplain {
// JSON形式遍历分析不方便,转成Row格式统一处理
rows = database.ConvertExplainJSON2Row(exp.ExplainJSON)
}
for _, row := range rows {
if len(row.PossibleKeys) < common.Config.ExplainMinPossibleKeys {
tablesSuggests[row.TableName] = append(tablesSuggests[row.TableName], fmt.Sprintf("PossibleKeys:%d < %d",
len(row.PossibleKeys), common.Config.ExplainMinPossibleKeys))
}
}
}
*/
// TODO:
/*
func checkExplainKeyLen(exp *database.ExplainInfo) {
}
*/
// TODO:
/*
func checkExplainKey(exp *database.ExplainInfo) {
// 小于最小使用试用key数量
//return intval($explainResult) < intval($userCond);
//explain-min-keys int
}
func checkExplainExtra(exp *database.ExplainInfo) {
// 包含用户配置的逗号分隔关键词之一则提醒
// return self::contains($explainResult, $userCond);
// explain-warn-extra []string
}
*/
// checkExplainRef ...
func
checkExplainRef
(
exp
*
database
.
ExplainInfo
)
{
rows
:=
exp
.
ExplainRows
if
exp
.
ExplainFormat
==
database
.
JSONFormatExplain
{
...
...
@@ -148,6 +126,7 @@ func checkExplainRef(exp *database.ExplainInfo) {
}
}
// checkExplainRows ...
func
checkExplainRows
(
exp
*
database
.
ExplainInfo
)
{
// 判断是否跳过不检查
if
common
.
Config
.
ExplainMaxRows
<=
0
{
...
...
@@ -167,15 +146,7 @@ func checkExplainRows(exp *database.ExplainInfo) {
}
}
// TODO:
/*
func checkExplainExtra(exp *database.ExplainInfo) {
// 包含用户配置的逗号分隔关键词之一则提醒
// return self::contains($explainResult, $userCond);
// explain-warn-extra []string
}
*/
// checkExplainFiltered ...
func
checkExplainFiltered
(
exp
*
database
.
ExplainInfo
)
{
// 判断是否跳过不检查
if
common
.
Config
.
ExplainMaxFiltered
<=
0.001
{
...
...
@@ -235,30 +206,7 @@ func ExplainAdvisor(exp *database.ExplainInfo) map[string]Rule {
Func
:
(
*
Query4Audit
)
.
RuleOK
,
}
}
/*
for t, s := range tablesSuggests {
// 检查explain对应的表是否需要跳过,如dual,空表等
ig := false
for _, ti := range explainIgnoreTables {
if ti == t {
ig = true
}
}
if ig {
continue
}
ruleId := fmt.Sprintf("EXP.%03d", explainRuleId+1)
explainRuleId = explainRuleId + 1
explainRules[ruleId] = Rule{
Item: ruleId,
Severity: "L0",
Summary: fmt.Sprintf("表 `%s` 查询效率不高", t),
Content: fmt.Sprint("原因:", strings.Join(s, ",")),
Case: "",
Func: (*Query4Audit).RuleOK,
}
}
*/
// TODO: 检查explain对应的表是否需要跳过,如dual,空表等
return
explainRules
}
...
...
advisor/index.go
浏览文件 @
5619dd32
...
...
@@ -665,7 +665,7 @@ func (idxAdv *IndexAdvisor) buildIndex(idxList map[string]map[string][]*common.C
continue
}
idxName
:=
"idx_"
+
strings
.
Join
(
colNames
,
"_"
)
idxName
:=
common
.
Config
.
IdxPrefix
+
strings
.
Join
(
colNames
,
"_"
)
// 索引名称最大长度64
if
len
(
idxName
)
>
IndexNameMaxLength
{
...
...
@@ -699,7 +699,7 @@ func (idxAdv *IndexAdvisor) buildIndexWithNoEnv(indexList map[string]map[string]
common
.
Log
.
Warn
(
"can not get the meta info of column '%s'"
,
col
.
Name
)
continue
}
idxName
:=
"idx_"
+
col
.
Name
idxName
:=
common
.
Config
.
IdxPrefix
+
col
.
Name
// 库、表、列名需要用反撇转义
alterSQL
:=
fmt
.
Sprintf
(
"alter table `%s`.`%s` add index `%s` (`%s`)"
,
idxAdv
.
vEnv
.
RealDB
(
col
.
DB
),
col
.
Table
,
idxName
,
col
.
Name
)
if
col
.
DB
==
""
{
...
...
advisor/rules_test.go
浏览文件 @
5619dd32
...
...
@@ -48,10 +48,16 @@ func TestListHeuristicRules(t *testing.T) {
func
TestInBlackList
(
t
*
testing
.
T
)
{
common
.
Log
.
Debug
(
"Entering function: %s"
,
common
.
GetFunctionName
())
sqls
:=
[]
string
{
"select"
,
"select 1"
,
}
common
.
BlackList
=
[]
string
{
"select"
}
if
!
InBlackList
(
"select 1"
)
{
for
_
,
sql
:=
range
sqls
{
if
!
InBlackList
(
sql
)
{
t
.
Error
(
"should be true"
)
}
}
common
.
Log
.
Debug
(
"Exiting function: %s"
,
common
.
GetFunctionName
())
}
...
...
ast/rewrite.go
浏览文件 @
5619dd32
...
...
@@ -40,7 +40,10 @@ type Rule struct {
}
// RewriteRules SQL重写规则,注意这个规则是有序的,先后顺序不能乱
var
RewriteRules
=
[]
Rule
{
var
RewriteRules
[]
Rule
func
init
()
{
RewriteRules
=
[]
Rule
{
{
Name
:
"dml2select"
,
Description
:
"将数据库更新请求转换为只读查询请求,便于执行EXPLAIN"
,
...
...
@@ -214,6 +217,7 @@ var RewriteRules = []Rule{
},
// TODO in to exists
// TODO exists to in
}
}
// ListRewriteRules 打印SQL重写规则
...
...
@@ -842,7 +846,7 @@ func (rw *Rewrite) RewriteAddOrderByNull() *Rewrite {
}
// RewriteOr2Union or2union: 将 OR 查询转写为 UNION ALL TODO: 暂无对应 HeuristicRules
// https://sqlperformance.com/2014/09/sql-plan/rewriting-queries-improve-performance
//
TODO:
https://sqlperformance.com/2014/09/sql-plan/rewriting-queries-improve-performance
func
(
rw
*
Rewrite
)
RewriteOr2Union
()
*
Rewrite
{
return
rw
}
...
...
cmd/soar/soar_test.go
浏览文件 @
5619dd32
...
...
@@ -18,6 +18,7 @@ package main
import
(
"flag"
"fmt"
"testing"
"github.com/XiaoMi/soar/common"
...
...
@@ -42,32 +43,42 @@ func TestMain(m *testing.M) {
}
func
Test_Main
(
_
*
testing
.
T
)
{
common
.
Log
.
Debug
(
"Entering function: %s"
,
common
.
GetFunctionName
())
common
.
Config
.
OnlineDSN
.
Disable
=
true
common
.
Config
.
LogLevel
=
0
common
.
Config
.
Query
=
"select * from film;alter table city add index idx_country_id(country_id);"
main
()
common
.
Log
.
Debug
(
"Exiting function: %s"
,
common
.
GetFunctionName
())
}
func
Test_Main_More
(
_
*
testing
.
T
)
{
common
.
Log
.
Debug
(
"Entering function: %s"
,
common
.
GetFunctionName
())
common
.
Config
.
LogLevel
=
0
common
.
Config
.
Profiling
=
true
common
.
Config
.
Explain
=
true
common
.
Config
.
Query
=
"select * from film where country_id = 1;use sakila;alter table city add index idx_country_id(country_id);"
orgRerportType
:=
common
.
Config
.
ReportType
for
_
,
typ
:=
range
[]
string
{
"json"
,
"html"
,
"markdown"
,
"fingerprint"
,
"compress"
,
"pretty"
,
"rewrite"
,
"ast"
,
"tiast"
,
"ast-json"
,
"tiast-json"
,
"tokenize"
,
}
{
common
.
Config
.
ReportType
=
typ
main
()
}
common
.
Config
.
ReportType
=
orgRerportType
common
.
Log
.
Debug
(
"Exiting function: %s"
,
common
.
GetFunctionName
())
}
func
Test_Main_checkConfig
(
t
*
testing
.
T
)
{
common
.
Log
.
Debug
(
"Entering function: %s"
,
common
.
GetFunctionName
())
if
checkConfig
()
!=
0
{
t
.
Error
(
"checkConfig error"
)
}
common
.
Log
.
Debug
(
"Exiting function: %s"
,
common
.
GetFunctionName
())
}
func
Test_Main_initQuery
(
t
*
testing
.
T
)
{
common
.
Log
.
Debug
(
"Entering function: %s"
,
common
.
GetFunctionName
())
// direct query
query
:=
initQuery
(
"select 1"
)
if
query
!=
"select 1"
{
...
...
@@ -79,4 +90,17 @@ func Test_Main_initQuery(t *testing.T) {
// TODO: read from stdin
// initQuery("")
common
.
Log
.
Debug
(
"Exiting function: %s"
,
common
.
GetFunctionName
())
}
func
Test_Main_reportTool
(
t
*
testing
.
T
)
{
common
.
Log
.
Debug
(
"Entering function: %s"
,
common
.
GetFunctionName
())
orgRerportType
:=
common
.
Config
.
ReportType
types
:=
[]
string
{
"html"
,
"md2html"
,
"explain-digest"
,
"chardet"
,
"remove-comment"
}
for
_
,
tp
:=
range
types
{
common
.
Config
.
ReportType
=
tp
fmt
.
Println
(
reportTool
(
tp
,
[]
byte
{}))
}
common
.
Config
.
ReportType
=
orgRerportType
common
.
Log
.
Debug
(
"Exiting function: %s"
,
common
.
GetFunctionName
())
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录