【问题标题】:Does the order of conditions in a WHERE clause affect MySQL performance?WHERE 子句中的条件顺序是否会影响 MySQL 性能?
【发布时间】:2010-06-15 06:44:28
【问题描述】:

假设我有一个长而昂贵的查询,包含条件,搜索大量行。我还有一个特殊条件,比如公司 id,它将大大限制需要搜索的行数,将其从数十万缩小到数十。

我这样做对 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) 

【问题讨论】:

标签: mysql sql


【解决方案1】:

不,订单不应该有很大的不同。在查找与条件匹配的行时,会针对每一行检查整个条件(通过布尔逻辑组合的所有子条件)。

一些智能数据库引擎会尝试猜测可以更快地评估条件的哪些部分(例如,不使用内置函数的事物)并首先评估那些部分,然后再评估更复杂(估计)的元素.这是由数据库引擎决定的,而不是 SQL。

【讨论】:

  • 我不认为你是对的。如果没有必要,不会简单地扫描表格以评估条件。例如,如果“公司”存在索引。第一个子集选择是使用索引完成的。如果公司不首先被评估,那么该指数就不能再使用了。但是,复杂的 DBMS 应该能够决定首先评估哪个条件来优化查询。
  • P.S. (不能再编辑我的评论):当然你在第二部分是对的,但我怀疑“条件作为一个整体......对每一行进行评估”这句话。
  • @chiccodoro:我认为优化器会解决这个问题。
  • @chiccodoro:对不起,我的措辞不好。不应该被评估,应该被更多地“审查”。已评估意味着找到每个部分的值,这不是我说的。
  • 为了允许优化(索引的使用),您可能需要正确订购 WHERE。例如,LIKE 应该在您的最后一个条件中,第一个条件基于索引。我不确定哪个数据库会自动进行哪些优化,因为这个特定的没有很好的记录。
【解决方案2】:

where 子句中列的顺序并不重要,因为 MySQL 会在执行之前优化查询。但我建议您阅读 MySQL 参考手册中关于Optimization 的章节,了解如何分析查询和表,并在必要时对其进行优化。不过,就我个人而言,我总是会尝试将索引字段放在非索引字段之前,并根据它们应该返回的行数对它们进行排序(最严格的条件首先,最不严格的最后)。

【讨论】:

    【解决方案3】:

    Here is a demo 显示 WHERE 子句条件的顺序 可以由于短路而有所不同。它运行以下查询:

    -- query #1
    SELECT myint FROM mytable WHERE myint >= 3 OR myslowfunction('query #1', myint) = 1;
    
    -- query #2
    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 条件的左侧时,它会执行更多次。

    所以 IMO 问题的答案:

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

    是“有时它可以做到。”

    【讨论】:

      【解决方案4】:

      数学上是的它有效果。不仅在 SQL 查询中。而是在所有编程语言中,只要有 and / or 的表达式。 有一种完全评估或部分评估的理论。 如果它的一个和查询和and 的第一个表达式计算为假,它将不会进一步检查。 as anding false 与任何东西都会产生 false 。 同样,在 or 表达式中,如果第一个为真,则不会进一步检查。

      【讨论】:

      • 它们不是唯一的选择。一些语言有短路评估。一些承诺评估所有的表达式。其他人则有惰性评估,并且仅以未定义的顺序评估他们需要的内容。 SQL(显然)可以选择自己的评估顺序来进行最佳短路评估。
      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

          我认为 where 子句的顺序没有任何影响。我认为 MySQL 查询优化器会按照它认为合适的方式重新组织 where 子句,因此它会首先过滤掉最大的子集。

          在谈论联接时,这是另一回事。优化器也尝试在这里重新排序,但并不总能找到最佳方式,有时也不使用索引。 SELECT STRAIGHT JOIN 和 FORCE INDEX 让您负责查询。

          【讨论】:

            【解决方案8】:

            不,它没有,选择所需的表,然后逐行评估。顺序可以是任意的。

            【讨论】:

            • 这对于全表扫描来说是正确的,但很高兴数据库很少执行这种低效的方式。大多数情况下,它将在其(B 树)索引中搜索符合条件的条目。
            • 那么它就有效果了,因为如果一个条件的B-tree比另一个大,那么找到它的时间会更长。除非 mysql 对 AND 语句进行交集。然后没有。
            • 我刚刚改变了我拥有的 3 个子句的顺序,它有所作为。结果是不同的数据
            猜你喜欢
            • 2017-03-22
            • 2011-05-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-02-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多