使用multiple和子句执行Mysql查询的顺序是什么



类似,如果您有一个查询

select * from employee where name = "John Dao" and location = "New York" and salary > 1000

在这个查询中,AND子句是如何工作的。它会首先获取名为John Dao的结果集,并对获取的结果集执行位置过滤等操作吗。或它只是在满足所有条件的地方获取结果吗?

如果我们更改查询中AND语句的顺序,那么查询响应是否有任何更改?

WHERE子句中各种项的执行顺序是不确定的,您不能依赖于短路之类的东西(正如您在Java和C#等应用程序语言中所期望的那样(。如果您真的想确保按特定顺序进行逻辑求值,可以使用CASE表达式:

SELECT *
FROM employee
WHERE
CASE WHEN name <> 'John dao'     THEN 0
WHEN location <> 'New York' THEN 0
WHEN salary <= 1000         THEN 0
ELSE 1 END = 1;

上面的CASE表达式首先检查名称要求,如果名称不是John dao,则失败。接下来,它按照这个顺序检查位置,然后是工资。但是,以下WHERE子句中的求值顺序是未定义的:

WHERE name = 'John dao' AND location = 'New York' AND salary > 1000

不过,一般来说,一个好的数据库应该选择求值顺序,使WHERE子句执行得最快。也就是说,通常您不需要使用我上面使用的CASE表达式技巧。

WHERE name = 'John dao'
AND location = 'New York'
AND salary > 1000

情况1,没有相关索引:它将获取所有行,检查3列,直到其中一列失败或全部成功。除非存在复杂问题,如UDF、FULLTEXT、子查询、非确定性函数等,否则检查顺序无关紧要。数字和字符串、相等和不相等都无关紧要。

情况2:在这3列中的每一列上都有一个单独的INDEX优化器将使用可用的(尽管是粗略的(统计信息来决定3个子句中的哪一个将过滤掉最多的行。然后,通过使用PRIMARY KEY(隐式地附加到索引上(来定位数据的BTree中的数据行,将对数据进行另外两次检查。从该行中,它可以获取其他两列以完成筛选。MySQL在这种情况下很少使用多个索引。

情况3:INDEX(name, location, salary)INDEX(location, name, salary):这两种情况中的任何一种都是执行查询的最佳选择。请注意,使用=测试的列在INDEX中首先,而与WHERE中的顺序无关。它将从BTree向下钻到纽约第一个薪水>1000的John dao。然后它将在B+树中向前扫描以找到所有这样的行。假设(SELECT *的(*涉及的列多于这3列,则情况3将不得不进入数据BTree以获取其余列。注意,这比情况2要好,因为它在进入另一个BTree之前完成了所有的过滤。

有关设计最佳索引的更多信息:http://mysql.rjweb.org/doc.php/index_cookbook_mysql

最新更新