mysql程序员

mysql的查询顺序解析

2017-04-20  本文已影响0人  小灰灰besty

mysql的使用过成中,SELECT的使用是非常频繁的,那么理解SELECT的查询操作就显得非常重要。

对于查询处理,可将其分为逻辑查询处理和物理查询处理。逻辑查询处理表示执行查询应该产生什么样的结果,而物理查询代表mysql数据库是如何得到该结果的。两种查询的方法可能完全不同,但是得到的结果是相同的。


1.逻辑查询处理

SQL的逻辑查询处理的顺序如下:

(7)    SELECT

(8)     DISTINCT 

(1)     FROM 

(3)      JOIN 

(2)     ON 

(4)     WHERE 

(5)     GROUP BY 

(6)     HAVING 

(9)     ORDER BY 

(10)    LIMIT 

我们老具体分析查询处理的各个阶段:

FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1

ON: 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中。

JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。

WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。

GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.

CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.

HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中。

SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。

DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.

ORDER BY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10.

LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

2.物理查询处理

虽然SQL的逻辑查询是根据上述进行查询,但是数据库也许并不会完全按照逻辑查询处理的方式来进行查询。MYSQL数据库有两个组件Parser(分析SQL语句)和Optimizer(优化)。

从官方手册上看,可以理解为,MySQL采用了基于开销的优化器,以确定处理查询的最解方式,也就是说执行查询之前,都会先选择一条自以为最优的方案,然后执行这个方案来获取结果。在很多情况下,MySQL能够计算最佳的可能查询计划,但在某些情况下,MySQL没有关于数据的足够信息,或者是提供太多的相关数据信息,估测就不那么友好了。

1.本人认为解析器解析后的执行顺序是有写变化,首先讨论没有创建索引的情况,having和group by的顺序应该在select之后:

FROM clause

WHERE clause

SELECT clause

GROUP BY clause

HAVING clause

ORDER BY clause

为什么这样说呢,因为mysql中允许在having和group by语句中使用别名(alias),但where语句中是不能直接使用select语句中的别名的,我们来看一个例子:

mysql> select * from formatting;

+---------+------------+-------+--------+-----+

| orderid | orderdate  | empid | custid | qty |

+---------+------------+-------+--------+-----+

|      1 | 2010-01-02 |    3 | A      |  10 |

|      2 | 2010-04-02 |    2 | B      |  20 |

|      3 | 2010-05-02 |    1 | A      |  30 |

|      4 | 2010-07-02 |    3 | D      |  40 |

|      5 | 2011-01-02 |    4 | A      |  20 |

|      6 | 2011-01-02 |    3 | B      |  30 |

|      7 | 2011-01-02 |    1 | C      |  40 |

|      8 | 2009-01-02 |    2 | A      |  10 |

|      9 | 2009-01-02 |    3 | B      |  20 |

+---------+------------+-------+--------+-----+

9 rows in set (0.00 sec)

在where中使用别名,数据库返回error说找不到where中的id列,说明数据库还没有解析select。

mysql> select custid as id,count(orderid) as cnt from formatting where id='A';

ERROR 1054 (42S22): Unknown column 'id' in 'where clause'

但是在group by和having中使用别名mysql可以成功解析。

mysql> select custid as id,count(orderid) as cnt from formatting group by id having cnt>2;

+----+-----+

| id | cnt |

+----+-----+

| A  |  4 |

| B  |  3 |

+----+-----+

2 rows in set (0.00 sec)

2.存在索引的情况下,优化器优先使用条件用到索引且最优的方案,通过例子来看。

    当sql条件有多个索引可以选择,且存在索引能唯一定位结果时,mysql优化器将直接使用效率最高的索引执行。

当结果是某个集合时,mysql优化器将使用merge索引的方式提高查询效率,并且虽然我的where顺序是更少数值的在后面,但mysql优化器会自动修正顺序,先查找empid的索引。

从这里可以看出索引的建立对于sql的优化是有一定关键作用的。但不是所有的优化器使用的都是最优的方式,可以具体方案具体分析。

上一篇下一篇

猜你喜欢

热点阅读