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

add KEY.010

  FULLTEXT INDEX suggestion
上级 62b08a21
......@@ -2704,6 +2704,38 @@ func (q *Query4Audit) RuleUniqueKeyDup() Rule {
return rule
}
// RuleFulltextIndex KEY.010
func (q *Query4Audit) RuleFulltextIndex() Rule {
var rule = q.RuleOK()
/* // TiDB parser
for _, tiStmt := range q.TiStmt {
switch tiStmt.(type) {
case *tidb.CreateTableStmt, *tidb.AlterTableStmt:
default:
return rule
}
}
*/
switch q.Stmt.(type) {
case *sqlparser.DDL:
default:
return rule
}
tks := ast.Tokenize(q.Query)
for _, tk := range tks {
switch tk.Type {
case ast.TokenTypeWord:
if strings.TrimSpace(strings.ToUpper(tk.Val)) == "FULLTEXT" {
rule = HeuristicRules["KEY.010"]
}
default:
}
}
return rule
}
// RuleTimestampDefault COL.013
func (q *Query4Audit) RuleTimestampDefault() Rule {
var rule = q.RuleOK()
......
......@@ -2130,6 +2130,7 @@ func TestCompareWithFunction(t *testing.T) {
{
`select id from t where substring(name,1,3)='abc';`,
`SELECT * FROM tbl WHERE UNIX_TIMESTAMP(loginTime) BETWEEN UNIX_TIMESTAMP('2018-11-16 09:46:00 +0800 CST') AND UNIX_TIMESTAMP('2018-11-22 00:00:00 +0800 CST')`,
`select id from t where num/2 = 100`,
},
// TODO: 右侧使用函数比较
{
......@@ -2596,6 +2597,47 @@ func TestRuleUniqueKeyDup(t *testing.T) {
common.Log.Debug("Exiting function: %s", common.GetFunctionName())
}
// KEY.010
func TestRuleFulltextIndex(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
sqls := [][]string{
{
`ALTER TABLE tb ADD FULLTEXT INDEX ip (ip);`,
// `CREATE FULLTEXT INDEX ft_ip ON tb (ip);`, // TODO: tidb not support yet
`CREATE TABLE tb ( id int(10) unsigned NOT NULL AUTO_INCREMENT, ip varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (id), FULLTEXT KEY ip (ip) ) ENGINE=InnoDB;`,
},
{
`ALTER TABLE tbl add INDEX idx_col (col);`,
`CREATE INDEX part_of_name ON customer (name(10));`,
},
}
for _, sql := range sqls[0] {
q, err := NewQuery4Audit(sql)
if err == nil {
rule := q.RuleFulltextIndex()
if rule.Item != "KEY.010" {
t.Error("Rule not match:", rule.Item, "Expect : KEY.010")
}
} else {
t.Error("sqlparser.Parse Error:", err)
}
}
for _, sql := range sqls[1] {
q, err := NewQuery4Audit(sql)
if err == nil {
rule := q.RuleFulltextIndex()
if rule.Item != "OK" {
t.Error("Rule not match:", rule.Item, "Expect : OK")
}
} else {
t.Error("sqlparser.Parse Error:", err)
}
}
common.Log.Debug("Exiting function: %s", common.GetFunctionName())
}
// COL.013
func TestRuleTimestampDefault(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
......
......@@ -796,6 +796,14 @@ func init() {
Case: "CREATE UNIQUE INDEX part_of_name ON customer (name(10));",
Func: (*Query4Audit).RuleUniqueKeyDup,
},
"KEY.010": {
Item: "KEY.010",
Severity: "L0",
Summary: "全文索引不是银弹",
Content: `全文索引主要用于解决模糊查询的性能问题,但需要控制好查询的频率和并发度。同时注意调整 ft_min_word_len, ft_max_word_len, ngram_token_size 等参数。`,
Case: "CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ip` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), FULLTEXT KEY `ip` (`ip`) ) ENGINE=InnoDB;",
Func: (*Query4Audit).RuleFulltextIndex,
},
"KWR.001": {
Item: "KWR.001",
Severity: "L2",
......
......@@ -812,6 +812,16 @@ SELECT * FROM tbl ORDER BY a DESC, b ASC;
```sql
CREATE UNIQUE INDEX part_of_name ON customer (name(10));
```
## 全文索引不是银弹
* **Item**:KEY.010
* **Severity**:L0
* **Content**:全文索引主要用于解决模糊查询的性能问题,但需要控制好查询的频率和并发度。同时注意调整 ft\_min\_word\_len, ft\_max\_word\_len, ngram\_token\_size 等参数。
* **Case**:
```sql
CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ip` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), FULLTEXT KEY `ip` (`ip`) ) ENGINE=InnoDB;
```
## SQL\_CALC\_FOUND\_ROWS 效率低下
* **Item**:KWR.001
......
......@@ -75,6 +75,7 @@ advisor.Rule{Item:"KEY.006", Severity:"L4", Summary:"主键中的列过多", Con
advisor.Rule{Item:"KEY.007", Severity:"L4", Summary:"未指定主键或主键非 int 或 bigint", Content:"未指定主键或主键非 int 或 bigint,建议将主键设置为 int unsigned 或 bigint unsigned。", Case:"CREATE TABLE tbl (a int);", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KEY.008", Severity:"L4", Summary:"ORDER BY 多个列但排序方向不同时可能无法使用索引", Content:"在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。", Case:"SELECT * FROM tbl ORDER BY a DESC, b ASC;", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KEY.009", Severity:"L0", Summary:"添加唯一索引前请注意检查数据唯一性", Content:"请提前检查添加唯一索引列的数据唯一性,如果数据不唯一在线表结构调整时将有可能自动将重复列删除,这有可能导致数据丢失。", Case:"CREATE UNIQUE INDEX part_of_name ON customer (name(10));", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KEY.010", Severity:"L0", Summary:"全文索引不是银弹", Content:"全文索引主要用于解决模糊查询的性能问题,但需要控制好查询的频率和并发度。同时注意调整 ft_min_word_len, ft_max_word_len, ngram_token_size 等参数。", Case:"CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ip` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), FULLTEXT KEY `ip` (`ip`) ) ENGINE=InnoDB;", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KWR.001", Severity:"L2", Summary:"SQL_CALC_FOUND_ROWS 效率低下", Content:"因为 SQL_CALC_FOUND_ROWS 不能很好地扩展,所以可能导致性能问题; 建议业务使用其他策略来替代 SQL_CALC_FOUND_ROWS 提供的计数功能,比如:分页结果展示等。", Case:"select SQL_CALC_FOUND_ROWS col from tbl where id>1000", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KWR.002", Severity:"L2", Summary:"不建议使用 MySQL 关键字做列名或表名", Content:"当使用关键字做为列名或表名时程序需要对列名和表名进行转义,如果疏忽被将导致请求无法执行。", Case:"CREATE TABLE tbl ( `select` int )", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KWR.003", Severity:"L1", Summary:"不建议使用复数做列名或表名", Content:"表名应该仅仅表示表里面的实体内容,不应该表示实体数量,对应于 DO 类名也是单数形式,符合表达习惯。", Case:"CREATE TABLE tbl ( `books` int )", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
......
......@@ -812,6 +812,16 @@ SELECT * FROM tbl ORDER BY a DESC, b ASC;
```sql
CREATE UNIQUE INDEX part_of_name ON customer (name(10));
```
## 全文索引不是银弹
* **Item**:KEY.010
* **Severity**:L0
* **Content**:全文索引主要用于解决模糊查询的性能问题,但需要控制好查询的频率和并发度。同时注意调整 ft\_min\_word\_len, ft\_max\_word\_len, ngram\_token\_size 等参数。
* **Case**:
```sql
CREATE TABLE `tb` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `ip` varchar(255) NOT NULL DEFAULT '', PRIMARY KEY (`id`), FULLTEXT KEY `ip` (`ip`) ) ENGINE=InnoDB;
```
## SQL\_CALC\_FOUND\_ROWS 效率低下
* **Item**:KWR.001
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册