WHERE子句中的条件顺序是否会影响MySQL性能?

问题描述:

假设我有一个漫长而昂贵的查询,它满足条件,搜索大量的行。我还有一个特殊的条件,比如公司ID,它会限制需要搜索的行数,从而缩小到数十万。WHERE子句中的条件顺序是否会影响MySQL性能?

它使MySQL的性能有什么区别我是否做到这一点:

SELECT * FROM clients WHERE 
     (firstname LIKE :foo OR lastname LIKE :foo OR phone LIKE :foo) AND 
     (firstname LIKE :bar OR lastname LIKE :bar OR phone LIKE :bar) AND 
     company = :ugh 

或本:

SELECT * FROM clients WHERE 
     company = :ugh AND 
     (firstname LIKE :foo OR lastname LIKE :foo OR phone LIKE :foo) AND 
     (firstname LIKE :bar OR lastname LIKE :bar OR phone LIKE :bar) 
+3

MySQL也有'EXPLAIN

+0

本节可能会有所帮助:[WHERE子句optomisations](https://dev.mysql .COM/DOC/refman/5.5/EN /其中,optimizations.html) – will 2016-09-20 02:40:58

号,顺序不应该带来很大的不同。在查找哪些行与条件匹配时,会针对每行检查整个条件(通过布尔逻辑组合的所有子条件)。

一些智能数据库引擎将尝试猜测可以更快地评估条件的哪些部分(例如,不使用内置函数的东西),并首先评估这些条件并评估更复杂(估计)的元素后来。这是由DB引擎确定的,但不是SQL。

+1

我不认为你是对的。如果没有必要,表格不会简单地扫描以评估条件。例如,如果“公司”存在索引。第一个子集选择使用索引完成。如果公司不会被首先评估,那么指数就不能再被使用了。但是,一个复杂的DBMS应该能够决定首先评估哪个条件来优化查询。 – chiccodoro 2010-06-15 06:52:51

+0

P.S. (不能再修改我的意见):当然,你说得对,你第二部分,但声明“的条件作为一个整体......对每个行计算”是什么,我怀疑。 – chiccodoro 2010-06-15 06:59:36

+0

@chiccodoro:我认为优化器会照顾到这一点。 – Gumbo 2010-06-15 07:15:29

不,不需要,需要的表格被选中,然后逐行评估。顺序可以是任意的。

+2

这将是真正的全表扫描,而是欣然数据库有很少进行这样的inefficent方式。 主要是它将在其(B树)索引搜索匹配的标准entrys。 – 2010-06-15 15:55:17

这不应该有任何效果,但如果你不确定,为什么你不试试呢?从单个表中选择where子句的顺序没有区别,但是如果您连接多个表,则连接的顺序可能会影响执行(有时)。

一个复杂的数据库管理系统应该能够自己决定首先评估哪个条件。一些数据库提供工具来显示“策略”如何执行查询。在MySQL中,例如你可以输入EXPLAIN in front of a query。 DBMS然后打印它执行查询所执行的动作,例如,索引或全表扫描。因此,在两种情况下,您都可以一目了然地看到它是否使用“公司”索引。

我不认为where子句的顺序有什么影响。我认为MySQL查询优化器将重新组织where子句,因为它认为合适,所以它首先过滤掉最大的子集。

谈到连接时,这是另一个交易。优化器也尝试重新排序,但并不总是找到最佳方式,有时不使用索引。 SELECT STRAIGHT JOIN和FORCE INDEX让你负责查询。

你的where子句中列的顺序应该没有什么关系,因为MySQL在执行之前会优化查询。但我建议你阅读MySQL参考手册中关于Optimization的章节,以获得关于如何分析查询和表的基本概念,并在必要时优化它们。就个人而言,我总是试图将索引字段放在非索引字段之前,并根据它们应该返回的行数(先限制条件最多,限制最少)对其进行排序。

数学是的它有一个效果。不仅在SQL查询中。而是在所有编程语言中,只要有与and/or表达式。 有一个完整的评估或部分评估的理论。 如果它的an和query的第一个表达式and的计算结果为false,它将不会进一步检查。因为任何事情都是虚假的。 如果第一个是真的,那么在一个或表达式中模拟,它不会进一步检查。

+1

他们不是唯一的选择。有些语言有短路评估。一些承诺评估所有的表达式。其他人有懒惰的评估,只评估他们需要以一个未定义的顺序。 SQL(显然)可以选择自己的评估顺序来进行最佳短路评估。 – Oddthinking 2010-06-15 15:59:29

我发现自己与接受的答案不同意,并建立了一个测试,试图证明这一点:

http://rextester.com/HJGN96158

这将运行以下查询:

SELECT myint FROM mytable WHERE myint >= 3 OR myslowfunction('query #1', myint) = 1; 
SELECT myint FROM mytable WHERE myslowfunction('query #2', myint) = 1 OR myint >= 3; 

之间的唯一区别这是OR条件中操作数的顺序。

myslowfunction故意休眠第二和具有添加到日志表中的每个运行它时的条目的副作用。下面是运行上面的两个查询时,哪些将记录结果:

myslowfunction called for query #1 with value 1 
myslowfunction called for query #1 with value 2 
myslowfunction called for query #2 with value 1 
myslowfunction called for query #2 with value 2 
myslowfunction called for query #2 with value 3 
myslowfunction called for query #2 with value 4 

由上述可知,当它出现在一个OR条件左侧慢速功能被执行多次,当另一个操作数ISN” t总是如此(由于短路)。

所以IMO的问题的答案:

是否在一个条件的顺序WHERE子句影响MySQL的性能?

“是的,有时它可以做。”

+2

这应该是被接受的答案。 – 2017-04-21 17:27:17