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

Remove duplicate heuristict rule CLA.007

  CLA.007 is duplicate with KEY.007
上级 4b1eea87
......@@ -616,28 +616,6 @@ func (q *Query4Audit) RuleDiffGroupByOrderBy() Rule {
return rule
}
// RuleMixOrderBy CLA.007
func (q *Query4Audit) RuleMixOrderBy() Rule {
var rule = q.RuleOK()
var direction string
err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) {
switch n := node.(type) {
case sqlparser.OrderBy:
for _, order := range n {
// 比较相邻两个order by列的方向
if direction != "" && order.Direction != direction {
rule = HeuristicRules["CLA.007"]
return false, nil
}
direction = order.Direction
}
}
return true, nil
}, q.Stmt)
common.LogIfError(err, "")
return rule
}
// RuleExplicitOrderBy CLA.008
func (q *Query4Audit) RuleExplicitOrderBy() Rule {
var rule = q.RuleOK()
......
......@@ -340,26 +340,6 @@ func TestRuleDiffGroupByOrderBy(t *testing.T) {
common.Log.Debug("Exiting function: %s", common.GetFunctionName())
}
// CLA.007
func TestRuleMixOrderBy(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
sqls := []string{
"select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc",
}
for _, sql := range sqls {
q, err := NewQuery4Audit(sql)
if err == nil {
rule := q.RuleMixOrderBy()
if rule.Item != "CLA.007" {
t.Error("Rule not match:", rule.Item, "Expect : CLA.007")
}
} else {
t.Error("sqlparser.Parse Error:", err)
}
}
common.Log.Debug("Exiting function: %s", common.GetFunctionName())
}
// CLA.008
func TestRuleExplicitOrderBy(t *testing.T) {
common.Log.Debug("Entering function: %s", common.GetFunctionName())
......@@ -3016,9 +2996,13 @@ func TestRuleOrderByMultiDirection(t *testing.T) {
sqls := [][]string{
{
`SELECT col FROM tbl order by col desc, col2 asc`,
`SELECT col FROM tbl order by col desc, col2`,
`SELECT col FROM tbl order by col, col2 desc`,
},
{
`SELECT col FROM tbl order by col, col2`,
`SELECT col FROM tbl order by col desc, col2 desc`,
`SELECT col FROM tbl order by col asc, col2 asc`,
},
}
for _, sql := range sqls[0] {
......
......@@ -341,14 +341,6 @@ func InitHeuristicRules() {
Case: "select tb1.col, tb2.col from tb1, tb2 where id=1 group by tb1.col, tb2.col",
Func: (*Query4Audit).RuleDiffGroupByOrderBy,
},
"CLA.007": {
Item: "CLA.007",
Severity: "L2",
Summary: "ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引",
Content: `ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。`,
Case: "select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc",
Func: (*Query4Audit).RuleMixOrderBy,
},
"CLA.008": {
Item: "CLA.008",
Severity: "L2",
......@@ -830,7 +822,7 @@ func InitHeuristicRules() {
Item: "KEY.008",
Severity: "L4",
Summary: "ORDER BY 多个列但排序方向不同时可能无法使用索引",
Content: `在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。`,
Content: `在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。`,
Case: "SELECT * FROM tbl ORDER BY a DESC, b ASC;",
Func: (*Query4Audit).RuleOrderByMultiDirection,
},
......
......@@ -272,16 +272,6 @@ select id from test where id=1 order by id
```sql
select tb1.col, tb2.col from tb1, tb2 where id=1 group by tb1.col, tb2.col
```
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item**:CLA.007
* **Severity**:L2
* **Content**:ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
* **Case**:
```sql
select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item**:CLA.008
......@@ -846,7 +836,7 @@ CREATE TABLE tbl (a int);
* **Item**:KEY.008
* **Severity**:L4
* **Content**:在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content**:在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Case**:
```sql
......
......@@ -24,7 +24,6 @@ advisor.Rule{Item:"CLA.003", Severity:"L2", Summary:"不建议使用带 OFFSET
advisor.Rule{Item:"CLA.004", Severity:"L2", Summary:"不建议对常量进行 GROUP BY", Content:"GROUP BY 1 表示按第一列进行 GROUP BY。如果在 GROUP BY 子句中使用数字,而不是表达式或列名称,当查询列顺序改变时,可能会导致问题。", Case:"select col1,col2 from tbl group by 1", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"CLA.005", Severity:"L2", Summary:"ORDER BY 常数列没有任何意义", Content:"SQL 逻辑上可能存在错误; 最多只是一个无用的操作,不会更改查询结果。", Case:"select id from test where id=1 order by id", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"CLA.006", Severity:"L4", Summary:"在不同的表中 GROUP BY 或 ORDER BY", Content:"这将强制使用临时表和 filesort,可能产生巨大性能隐患,并且可能消耗大量内存和磁盘上的临时空间。", Case:"select tb1.col, tb2.col from tb1, tb2 where id=1 group by tb1.col, tb2.col", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"CLA.007", Severity:"L2", Summary:"ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引", Content:"ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。", Case:"select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"CLA.008", Severity:"L2", Summary:"请为 GROUP BY 显示添加 ORDER BY 条件", Content:"默认 MySQL 会对 'GROUP BY col1, col2, ...' 请求按如下顺序排序 'ORDER BY col1, col2, ...'。如果 GROUP BY 语句不指定 ORDER BY 条件会导致无谓的排序产生,如果不需要排序建议添加 'ORDER BY NULL'。", Case:"select c1,c2,c3 from t1 where c1='foo' group by c2", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"CLA.009", Severity:"L2", Summary:"ORDER BY 的条件为表达式", Content:"当 ORDER BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。", Case:"select description from film where title ='ACADEMY DINOSAUR' order by length-language_id;", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"CLA.010", Severity:"L2", Summary:"GROUP BY 的条件为表达式", Content:"当 GROUP BY 条件为表达式或函数时会使用到临时表,如果在未指定 WHERE 或 WHERE 条件返回的结果集较大时性能会很差。", Case:"select description from film where title ='ACADEMY DINOSAUR' GROUP BY length-language_id;", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
......@@ -78,7 +77,7 @@ advisor.Rule{Item:"KEY.004", Severity:"L0", Summary:"提醒:请将索引属性
advisor.Rule{Item:"KEY.005", Severity:"L2", Summary:"表建的索引过多", Content:"表建的索引过多", Case:"CREATE TABLE tbl ( a int, b int, c int, KEY idx_a (`a`),KEY idx_b(`b`),KEY idx_c(`c`));", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
advisor.Rule{Item:"KEY.006", Severity:"L4", Summary:"主键中的列过多", Content:"主键中的列过多", Case:"CREATE TABLE tbl ( a int, b int, c int, PRIMARY KEY(`a`,`b`,`c`));", Position:0, Func:func(*advisor.Query4Audit) advisor.Rule {...}}
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.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 {...}}
......
......@@ -5,8 +5,8 @@
Table: "film",
DB: "sakila",
DataType: "smallint unsigned",
Character: "utf8",
Collation: "utf8_general_ci",
Character: "utf8mb3",
Collation: "utf8mb3_general_ci",
Cardinality: 0,
Null: "",
Key: "",
......
......@@ -15,7 +15,7 @@
{
Field: "first_name",
Type: "varchar(45)",
Collation: {0x75, 0x74, 0x66, 0x38, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x69},
Collation: {0x75, 0x74, 0x66, 0x38, 0x6d, 0x62, 0x33, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x69},
Null: "NO",
Key: "",
Default: nil,
......@@ -26,7 +26,7 @@
{
Field: "last_name",
Type: "varchar(45)",
Collation: {0x75, 0x74, 0x66, 0x38, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x69},
Collation: {0x75, 0x74, 0x66, 0x38, 0x6d, 0x62, 0x33, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x69},
Null: "NO",
Key: "",
Default: nil,
......@@ -37,7 +37,7 @@
{
Field: "film_info",
Type: "text",
Collation: {0x75, 0x74, 0x66, 0x38, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x69},
Collation: {0x75, 0x74, 0x66, 0x38, 0x6d, 0x62, 0x33, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x69},
Null: "YES",
Key: "",
Default: nil,
......
......@@ -272,16 +272,6 @@ select id from test where id=1 order by id
```sql
select tb1.col, tb2.col from tb1, tb2 where id=1 group by tb1.col, tb2.col
```
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item**:CLA.007
* **Severity**:L2
* **Content**:ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
* **Case**:
```sql
select c1,c2,c3 from t1 where c1='foo' order by c2 desc, c3 asc
```
## 请为 GROUP BY 显示添加 ORDER BY 条件
* **Item**:CLA.008
......@@ -846,7 +836,7 @@ CREATE TABLE tbl (a int);
* **Item**:KEY.008
* **Severity**:L4
* **Content**:在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content**:在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Case**:
```sql
......
......@@ -577,7 +577,7 @@ ORDER BY
# Query: 6E9B96CA3F0E6BDA
★ ★ ★ ☆ ☆ 65分
★ ★ ★ ☆ ☆ 75分
```sql
......@@ -591,14 +591,6 @@ ORDER BY
release_year ASC, language_id DESC
```
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
......@@ -613,7 +605,7 @@ ORDER BY
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content:** 在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: 2EAACFD7030EA528
......@@ -2024,7 +2016,7 @@ FROM
# Query: E48A20D0413512DA
★ ★ ☆ ☆ ☆ 50分
★ ★ ★ ☆ ☆ 60分
```sql
......@@ -2056,14 +2048,6 @@ ORDER BY
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 同一张表被连接两次
* **Item:** JOI.002
......@@ -2329,7 +2313,7 @@ ORDER BY
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content:** 在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: C11ECE7AE5F80CE5
......
......@@ -577,7 +577,7 @@ ORDER BY
# Query: 6E9B96CA3F0E6BDA
★ ★ ★ ☆ ☆ 65分
★ ★ ★ ☆ ☆ 75分
```sql
......@@ -591,14 +591,6 @@ ORDER BY
release_year ASC, language_id DESC
```
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
......@@ -613,7 +605,7 @@ ORDER BY
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content:** 在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: 2EAACFD7030EA528
......@@ -2024,7 +2016,7 @@ FROM
# Query: E48A20D0413512DA
★ ★ ☆ ☆ ☆ 50分
★ ★ ★ ☆ ☆ 60分
```sql
......@@ -2056,14 +2048,6 @@ ORDER BY
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 同一张表被连接两次
* **Item:** JOI.002
......@@ -2329,7 +2313,7 @@ ORDER BY
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content:** 在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: C11ECE7AE5F80CE5
......
......@@ -1233,7 +1233,7 @@ ORDER BY
# Query: 6E9B96CA3F0E6BDA
★ ★ ☆ ☆ ☆ 55分
★ ★ ★ ☆ ☆ 65分
```sql
......@@ -1284,14 +1284,6 @@ ORDER BY
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 不建议使用 SELECT * 类型查询
* **Item:** COL.001
......@@ -1306,7 +1298,7 @@ ORDER BY
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content:** 在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: 2EAACFD7030EA528
......@@ -2463,7 +2455,7 @@ FROM
| 1 | PRIMARY | *b* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.a.country\_id | 1 | ☠️ **100.00%** | O(log n) | NULL |
| 2 | UNION | *b* | NULL | ALL | NULL | NULL | NULL | NULL | 109 | ☠️ **100.00%** | ☠️ **O(n)** | NULL |
| 2 | UNION | *a* | NULL | ref | idx\_fk\_country\_id | idx\_fk\_country\_id | 2 | sakila.b.country\_id | 5 | ☠️ **100.00%** | O(log n) | NULL |
| 2 | UNION | *a* | NULL | ref | idx\_fk\_country\_id | idx\_fk\_country\_id | 2 | sakila.b.country\_id | 5 | ☠️ **100.00%** | O(log n) | NULL |
| 3 | UNION RESULT | *<union1,2>* | NULL | ALL | NULL | NULL | NULL | NULL | 0 | n% | ☠️ **O(n)** | Using temporary |
......@@ -2473,6 +2465,8 @@ FROM
* **PRIMARY**: 最外层的select.
* **UNION RESULT**: UNION查询的结果集.
* **UNION**: UNION中的第二个或后面的SELECT查询, 不依赖于外部查询的结果集.
#### Type信息解读
......@@ -2483,6 +2477,10 @@ FROM
* ☠️ **ALL**: 最坏的情况, 从头到尾全表扫描.
#### Extra信息解读
* ☠️ **Using temporary**: 表示MySQL在对查询结果排序时使用临时表. 常见于排序order by和分组查询group by.
## 建议使用 AS 关键字显示声明一个别名
......@@ -2539,7 +2537,7 @@ WHERE
| 1 | PRIMARY | *a* | NULL | ref | idx\_fk\_country\_id | idx\_fk\_country\_id | 2 | sakila.b.country\_id | 5 | n% | O(log n) | Using where; Not exists |
| 2 | UNION | *a* | NULL | ALL | NULL | NULL | NULL | NULL | 600 | ☠️ **100.00%** | ☠️ **O(n)** | NULL |
| 2 | UNION | *b* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.a.country\_id | 1 | n% | O(log n) | Using where; Not exists |
| 2 | UNION | *b* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.a.country\_id | 1 | n% | O(log n) | Using where; Not exists |
| 3 | UNION RESULT | *<union1,2>* | NULL | ALL | NULL | NULL | NULL | NULL | 0 | n% | ☠️ **O(n)** | Using temporary |
......@@ -2549,6 +2547,8 @@ WHERE
* **PRIMARY**: 最外层的select.
* **UNION RESULT**: UNION查询的结果集.
* **UNION**: UNION中的第二个或后面的SELECT查询, 不依赖于外部查询的结果集.
#### Type信息解读
......@@ -2565,6 +2565,8 @@ WHERE
* **Using where**: WHERE条件用于筛选出与下一个表匹配的数据然后返回给客户端. 除非故意做的全表扫描, 否则连接类型是ALL或者是index, 且在Extra列的值中没有Using Where, 则该查询可能是有问题的.
* ☠️ **Using temporary**: 表示MySQL在对查询结果排序时使用临时表. 常见于排序order by和分组查询group by.
## 为sakila库的city表添加索引
......@@ -3825,7 +3827,7 @@ FROM
| 1 | PRIMARY | *o* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.i.city\_id | 1 | ☠️ **100.00%** | O(log n) | NULL |
| 2 | UNION | *o* | NULL | ALL | NULL | NULL | NULL | NULL | 109 | ☠️ **100.00%** | ☠️ **O(n)** | NULL |
| 2 | UNION | *i* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.o.country\_id | 1 | ☠️ **100.00%** | O(log n) | NULL |
| 2 | UNION | *i* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.o.country\_id | 1 | ☠️ **100.00%** | O(log n) | NULL |
| 3 | UNION RESULT | *<union1,2>* | NULL | ALL | NULL | NULL | NULL | NULL | 0 | n% | ☠️ **O(n)** | Using temporary |
......@@ -3835,6 +3837,8 @@ FROM
* **PRIMARY**: 最外层的select.
* **UNION RESULT**: UNION查询的结果集.
* **UNION**: UNION中的第二个或后面的SELECT查询, 不依赖于外部查询的结果集.
#### Type信息解读
......@@ -3843,6 +3847,10 @@ FROM
* ☠️ **ALL**: 最坏的情况, 从头到尾全表扫描.
#### Extra信息解读
* ☠️ **Using temporary**: 表示MySQL在对查询结果排序时使用临时表. 常见于排序order by和分组查询group by.
## 建议使用 AS 关键字显示声明一个别名
......@@ -3993,7 +4001,7 @@ WHERE
| 1 | PRIMARY | *o* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.i.city\_id | 1 | ☠️ **100.00%** | O(log n) | Using where; Not exists |
| 2 | UNION | *o* | NULL | ALL | NULL | NULL | NULL | NULL | 109 | ☠️ **100.00%** | ☠️ **O(n)** | NULL |
| 2 | UNION | *i* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.o.country\_id | 1 | ☠️ **100.00%** | O(log n) | Using where; Not exists |
| 2 | UNION | *i* | NULL | eq\_ref | PRIMARY | PRIMARY | 2 | sakila.o.country\_id | 1 | ☠️ **100.00%** | O(log n) | Using where; Not exists |
| 3 | UNION RESULT | *<union1,2>* | NULL | ALL | NULL | NULL | NULL | NULL | 0 | n% | ☠️ **O(n)** | Using temporary |
......@@ -4003,6 +4011,8 @@ WHERE
* **PRIMARY**: 最外层的select.
* **UNION RESULT**: UNION查询的结果集.
* **UNION**: UNION中的第二个或后面的SELECT查询, 不依赖于外部查询的结果集.
#### Type信息解读
......@@ -4017,6 +4027,8 @@ WHERE
* **Using where**: WHERE条件用于筛选出与下一个表匹配的数据然后返回给客户端. 除非故意做的全表扫描, 否则连接类型是ALL或者是index, 且在Extra列的值中没有Using Where, 则该查询可能是有问题的.
* ☠️ **Using temporary**: 表示MySQL在对查询结果排序时使用临时表. 常见于排序order by和分组查询group by.
## 建议使用 AS 关键字显示声明一个别名
......@@ -4082,7 +4094,7 @@ FROM
# Query: E48A20D0413512DA
★ ★ ☆ ☆ ☆ 40分
★ ★ ☆ ☆ ☆ 50分
```sql
......@@ -4174,14 +4186,6 @@ ORDER BY
* **Content:** 在列或表别名(如"tbl AS alias")中, 明确使用 AS 关键字比隐含别名(如"tbl alias")更易懂。
## ORDER BY 语句对多个不同条件使用不同方向的排序无法使用索引
* **Item:** CLA.007
* **Severity:** L2
* **Content:** ORDER BY 子句中的所有表达式必须按统一的 ASC 或 DESC 方向排序,以便利用索引。
## 同一张表被连接两次
* **Item:** JOI.002
......@@ -4601,7 +4605,7 @@ ORDER BY
* **Severity:** L4
* **Content:** 在 MySQL 8.0之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
* **Content:** 在 MySQL 8.0 之前当 ORDER BY 多个列指定的排序方向不同时将无法使用已经建立的索引。
# Query: C11ECE7AE5F80CE5
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册