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} }}。
答案 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会遗漏索引。