MySQL首先执行什么:`WHERE`子句或`ORDER BY`子句?

时间:2015-08-21 01:28:49

标签: mysql database

MySQL首先执行什么:WHERE子句或ORDER BY子句?

我问的原因是确定是否应该为给定列添加索引。

我有一张如下表:

| Column    | Type        | Index | 
|-----------|-------------|-------| 
| id        | INT (pk)    | Yes   | 
| listorder | INT         | ??    | 
| data      | VARCHAR(16) | No    | 
| fk        | INT (fk)    | Yes   | 

我经常会执行SELECT id, data FROM mytable WHERE fk=12345 ORDER BY listorder ASC之类的查询。对于我的数据集,它只会为给定的fk生成少量记录(~5),但是,表中有许多记录包含许多fk个值,而且许多记录重复{ {1}}值涵盖了许多listorder值。

如果首先执行fk子句,那么我希望我不应该向WHERE添加索引,因为它会导致listorder性能下降{{1} }}。

3 个答案:

答案 0 :(得分:3)

SQL(所有服务器的品牌和型号)使用索引来满足查询的方式比您假设的要复杂一些。通常通过先过滤(WHERE)然后排序来满足查询。

对于您向我们展示的确切查询,如果您在(fk,listorder)上有复合索引,则SQL引擎将能够使用索引来满足查询的两个子句。该索引首先由WHERE子句随机访问,然后它将已经满足您的排序子句所需的顺序。

阅读本文:http://use-the-index-luke.com/

更新复合索引并不比更新单个列索引贵得多。无论哪种方式,使用索引比必须扫描表以进行WHERE操作更好。

答案 1 :(得分:2)

首先评估WHERE子句。我认为这在MySQL中总是如此,但可能偶尔会出现异常(至少在其他数据库中存在异常)。

对于此查询:

SELECT id, data
FROM mytable
WHERE fk = 12345
ORDER BY listorder ASC;

最实用的索引是mytable(fk, listorder)

答案 2 :(得分:1)

在SQL处理中,WHERE子句被视为隐式连接语句。事实上,它甚至相当于查询优化器中的INNER JOIN。较旧的ANSI语法仅在90年代早期采用INNER JOIN。许多旧的SQL select语句如下所示:

SELECT * 
FROM table1, table2
WHERE table1.ID = table2.ID

后来的黄金标准如下:

SELECT * 
FROM table1
INNER JOIN table2
ON table1.ID = table2.ID

然而,两个陈述都是等同的。但许多人认为INNER JOIN更具人性化。在INNER vs WHERE上看到这篇丰盛的SO帖子。

与大多数编程语言不同,在SQL中,语法的顺序并不决定处理的顺序。但具有讽刺意味的是,最后一行ORDER BY(除非声明了TOP或LIMIT)通常是最后一步,并且在FROM子句之后的第一步中是WHERE:

FROM table source
JOIN condition
WHERE condition
GROUP BY expression
HAVING condition
SELECT fields
ORDER BY fields

本质上,引擎构造由FROM,JOIN和WHERE子句确定的表和/或虚拟表。一旦设置了该结构,就会处理聚合,字段选择和排序。所以在你拿桌子之前你不能订购桌子!

指数几乎有助于处理的所有方面。在ORDER BY上设置索引不会导致性能下降。但是对齐WHERE和ORDER BY可以促进排序优化。见MySQL reference。事实上,众所周知,如果不需要,MySQL会遗漏索引。

相关问题