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

fix index col compare case sensitive bug

  CREATE TABLE test_id (
    ID int,
    PRIMARY KEY (`ID`)
  )
  SELECT * FROM test_id WHERE id=1;

  fix explain NULL able column bug

  +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
  | id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra                          |
  +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
  |  1 | SIMPLE      | NULL  | NULL       | NULL | NULL          | NULL | NULL    | NULL | NULL |     NULL | no matching row in const table |
  +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
上级 14c19f4d
...@@ -121,7 +121,7 @@ type Configuration struct { ...@@ -121,7 +121,7 @@ type Configuration struct {
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 int64 `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"` // 复杂度警告名单
...@@ -641,7 +641,7 @@ func readCmdFlags() error { ...@@ -641,7 +641,7 @@ func readCmdFlags() error {
explainWarnAccessType := flag.String("explain-warn-access-type", strings.Join(Config.ExplainWarnAccessType, ","), "ExplainWarnAccessType, 哪些access type不建议使用") explainWarnAccessType := flag.String("explain-warn-access-type", strings.Join(Config.ExplainWarnAccessType, ","), "ExplainWarnAccessType, 哪些access type不建议使用")
explainMaxKeyLength := flag.Int("explain-max-keys", Config.ExplainMaxKeyLength, "ExplainMaxKeyLength, 最大key_len") explainMaxKeyLength := flag.Int("explain-max-keys", Config.ExplainMaxKeyLength, "ExplainMaxKeyLength, 最大key_len")
explainMinPossibleKeys := flag.Int("explain-min-keys", Config.ExplainMinPossibleKeys, "ExplainMinPossibleKeys, 最小possible_keys警告") explainMinPossibleKeys := flag.Int("explain-min-keys", Config.ExplainMinPossibleKeys, "ExplainMinPossibleKeys, 最小possible_keys警告")
explainMaxRows := flag.Int("explain-max-rows", Config.ExplainMaxRows, "ExplainMaxRows, 最大扫描行数警告") explainMaxRows := flag.Int64("explain-max-rows", Config.ExplainMaxRows, "ExplainMaxRows, 最大扫描行数警告")
explainWarnExtra := flag.String("explain-warn-extra", strings.Join(Config.ExplainWarnExtra, ","), "ExplainWarnExtra, 哪些extra信息会给警告") explainWarnExtra := flag.String("explain-warn-extra", strings.Join(Config.ExplainWarnExtra, ","), "ExplainWarnExtra, 哪些extra信息会给警告")
explainMaxFiltered := flag.Float64("explain-max-filtered", Config.ExplainMaxFiltered, "ExplainMaxFiltered, filtered大于该配置给出警告") explainMaxFiltered := flag.Float64("explain-max-filtered", Config.ExplainMaxFiltered, "ExplainMaxFiltered, filtered大于该配置给出警告")
explainWarnScalability := flag.String("explain-warn-scalability", strings.Join(Config.ExplainWarnScalability, ","), "ExplainWarnScalability, 复杂度警告名单, 支持O(n),O(log n),O(1),O(?)") explainWarnScalability := flag.String("explain-warn-scalability", strings.Join(Config.ExplainWarnScalability, ","), "ExplainWarnScalability, 复杂度警告名单, 支持O(n),O(log n),O(1),O(?)")
......
...@@ -42,13 +42,16 @@ func ExampleIsColsPart() { ...@@ -42,13 +42,16 @@ func ExampleIsColsPart() {
b := []*Column{{Name: "1"}, {Name: "2"}} b := []*Column{{Name: "1"}, {Name: "2"}}
c := []*Column{{Name: "1"}, {Name: "3"}} c := []*Column{{Name: "1"}, {Name: "3"}}
d := []*Column{{Name: "1"}, {Name: "2"}, {Name: "3"}, {Name: "4"}} d := []*Column{{Name: "1"}, {Name: "2"}, {Name: "3"}, {Name: "4"}}
id := []*Column{{Name: "id"}}
iD := []*Column{{Name: "iD"}}
ab := IsColsPart(a, b) ab := IsColsPart(a, b)
ac := IsColsPart(a, c) ac := IsColsPart(a, c)
ad := IsColsPart(a, d) ad := IsColsPart(a, d)
idiD := IsColsPart(id, iD) // 大小写对比
fmt.Println(ab, ac, ad) fmt.Println(ab, ac, ad, idiD)
// Output: true false true // Output: true false true true
Log.Debug("Exiting function: %s", GetFunctionName()) Log.Debug("Exiting function: %s", GetFunctionName())
} }
......
...@@ -93,7 +93,9 @@ func IsColsPart(a, b []*Column) bool { ...@@ -93,7 +93,9 @@ func IsColsPart(a, b []*Column) bool {
} }
for i := 0; i < times; i++ { for i := 0; i < times; i++ {
if a[i].DB != b[i].DB || a[i].Table != b[i].Table || a[i].Name != b[i].Name { if strings.ToLower(a[i].DB) != strings.ToLower(b[i].DB) ||
strings.ToLower(a[i].Table) != strings.ToLower(b[i].Table) ||
strings.ToLower(a[i].Name) != strings.ToLower(b[i].Name) {
return false return false
} }
} }
......
...@@ -84,7 +84,7 @@ type ExplainRow struct { ...@@ -84,7 +84,7 @@ type ExplainRow struct {
Key string Key string
KeyLen string // 索引长度,如果发生了index_merge, KeyLen 格式为 N,N,所以不能定义为整型 KeyLen string // 索引长度,如果发生了index_merge, KeyLen 格式为 N,N,所以不能定义为整型
Ref []string Ref []string
Rows int Rows int64
Filtered float64 // 5.6 JSON, 5.7+, 5.5 EXTENDED Filtered float64 // 5.6 JSON, 5.7+, 5.5 EXTENDED
Scalability string // O(1), O(n), O(log n), O(log n)+ Scalability string // O(1), O(n), O(log n), O(log n)+
Extra string Extra string
...@@ -131,7 +131,7 @@ type ExplainJSONTable struct { ...@@ -131,7 +131,7 @@ type ExplainJSONTable struct {
UsedKeyParts []string `json:"used_key_parts"` UsedKeyParts []string `json:"used_key_parts"`
KeyLength string `json:"key_length"` KeyLength string `json:"key_length"`
Ref []string `json:"ref"` Ref []string `json:"ref"`
RowsExaminedPerScan int `json:"rows_examined_per_scan"` RowsExaminedPerScan int64 `json:"rows_examined_per_scan"`
RowsProducedPerJoin int `json:"rows_produced_per_join"` RowsProducedPerJoin int `json:"rows_produced_per_join"`
Filtered string `json:"filtered"` Filtered string `json:"filtered"`
UsingIndex bool `json:"using_index"` UsingIndex bool `json:"using_index"`
...@@ -318,6 +318,7 @@ var ExplainAccessType = map[string]string{ ...@@ -318,6 +318,7 @@ var ExplainAccessType = map[string]string{
// ExplainScalability ACCESS TYPE对应的运算复杂度 [AccessType]scalability map // ExplainScalability ACCESS TYPE对应的运算复杂度 [AccessType]scalability map
var ExplainScalability = map[string]string{ var ExplainScalability = map[string]string{
"NULL": "NULL",
"ALL": "O(n)", "ALL": "O(n)",
"index": "O(n)", "index": "O(n)",
"range": "O(log n)+", "range": "O(log n)+",
...@@ -784,7 +785,7 @@ func parseTraditionalExplainText(content string) (explainRows []ExplainRow, err ...@@ -784,7 +785,7 @@ func parseTraditionalExplainText(content string) (explainRows []ExplainRow, err
colsMap := make(map[string]string) colsMap := make(map[string]string)
for _, l := range lines[3:] { for _, l := range lines[3:] {
var keylen string var keylen string
var rows int var rows int64
var filtered float64 var filtered float64
var partitions string var partitions string
// 跳过分割线 // 跳过分割线
...@@ -816,7 +817,7 @@ func parseTraditionalExplainText(content string) (explainRows []ExplainRow, err ...@@ -816,7 +817,7 @@ func parseTraditionalExplainText(content string) (explainRows []ExplainRow, err
keylen = colsMap["key_len"] keylen = colsMap["key_len"]
rows, err = strconv.Atoi(colsMap["Rows"]) rows, err = strconv.ParseInt(colsMap["Rows"], 10, 64)
if err != nil { if err != nil {
rows = 0 rows = 0
} }
...@@ -908,7 +909,7 @@ func parseVerticalExplainText(content string) (explainRows []ExplainRow, err err ...@@ -908,7 +909,7 @@ func parseVerticalExplainText(content string) (explainRows []ExplainRow, err err
} }
if strings.HasPrefix(l, "Rows:") { if strings.HasPrefix(l, "Rows:") {
rows := strings.TrimPrefix(l, "Rows: ") rows := strings.TrimPrefix(l, "Rows: ")
explainRow.Rows, err = strconv.Atoi(rows) explainRow.Rows, err = strconv.ParseInt(rows, 10, 64)
if err != nil { if err != nil {
explainRow.Rows = 0 explainRow.Rows = 0
} }
...@@ -962,10 +963,16 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err ...@@ -962,10 +963,16 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | film | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL | | 1 | SIMPLE | film | NULL | ALL | NULL | NULL | NULL | NULL | 1000 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+ +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+
*/ */
// Different MySQL version has different columns define // Different MySQL version has different columns define
var selectType, table, partitions, accessType, possibleKeys, key, keyLen, ref, extra []byte var selectType, table, partitions, accessType, possibleKeys, key, keyLen, ref, extra, rows, filtered []byte
expRow := ExplainRow{} expRow := ExplainRow{}
explainFields := make([]interface{}, 0) explainFields := make([]interface{}, 0)
fields := map[string]interface{}{ fields := map[string]interface{}{
...@@ -978,8 +985,8 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err ...@@ -978,8 +985,8 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err
"key": &key, "key": &key,
"key_len": &keyLen, "key_len": &keyLen,
"ref": &ref, "ref": &ref,
"rows": &expRow.Rows, "rows": &rows,
"filtered": &expRow.Filtered, "filtered": &filtered,
"Extra": &extra, "Extra": &extra,
} }
cols, err := res.Rows.Columns() cols, err := res.Rows.Columns()
...@@ -1009,6 +1016,8 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err ...@@ -1009,6 +1016,8 @@ func ParseExplainResult(res QueryResult, formatType int) (exp *ExplainInfo, err
expRow.Key = NullString(key) expRow.Key = NullString(key)
expRow.KeyLen = NullString(keyLen) expRow.KeyLen = NullString(keyLen)
expRow.Ref = strings.Split(NullString(ref), ",") expRow.Ref = strings.Split(NullString(ref), ",")
expRow.Rows = NullInt(rows)
expRow.Filtered = NullFloat(filtered)
expRow.Extra = NullString(extra) expRow.Extra = NullString(extra)
// MySQL bug: https://bugs.mysql.com/bug.php?id=34124 // MySQL bug: https://bugs.mysql.com/bug.php?id=34124
...@@ -1115,8 +1124,10 @@ func PrintMarkdownExplainTable(exp *ExplainInfo) string { ...@@ -1115,8 +1124,10 @@ func PrintMarkdownExplainTable(exp *ExplainInfo) string {
} }
scalability := row.Scalability scalability := row.Scalability
for _, s := range common.Config.ExplainWarnScalability { for _, s := range common.Config.ExplainWarnScalability {
if s == scalability {
scalability = "☠️ **" + s + "**" scalability = "☠️ **" + s + "**"
} }
}
buf = append(buf, fmt.Sprintln("|", row.ID, " |", buf = append(buf, fmt.Sprintln("|", row.ID, " |",
common.MarkdownEscape(row.SelectType), common.MarkdownEscape(row.SelectType),
"| *"+common.MarkdownEscape(row.TableName)+"* |", "| *"+common.MarkdownEscape(row.TableName)+"* |",
......
...@@ -319,6 +319,24 @@ func NullString(buf []byte) string { ...@@ -319,6 +319,24 @@ func NullString(buf []byte) string {
return string(buf) return string(buf)
} }
// NullFloat null able float
func NullFloat(buf []byte) float64 {
if buf == nil {
return 0
}
f, _ := strconv.ParseFloat(string(buf), 64)
return f
}
// NullInt null able int
func NullInt(buf []byte) int64 {
if buf == nil {
return 0
}
i, _ := strconv.ParseInt(string(buf), 10, 64)
return i
}
// quoteEscape sql_mode=no_backslash_escapes // quoteEscape sql_mode=no_backslash_escapes
func quoteEscape(source string) string { func quoteEscape(source string) string {
var buf bytes.Buffer var buf bytes.Buffer
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册