在 MySQL 中,WHERE 子句中列的顺序会影响查询性能吗?

Pat*_*ick 43 mysql mysql-5 performance

我在某些具有大量可能结果集的数据库查询上遇到了性能问题。

有问题的查询,我AND在 WHERE 子句中有三个

条款的顺序重要吗?

就像,如果我把 ASI_EVENT_TIME 子句放在第一位(因为这会从任何子句中删除大部分结果。

这会改善查询的运行时间吗?

询问:

SELECT DISTINCT  activity_seismo_info.* 
FROM `activity_seismo_info` 
WHERE 
    activity_seismo_info.ASI_ACTIVITY_ID IS NOT NULL  AND 
    activity_seismo_info.ASI_SEISMO_ID IN (43,44,...,259) AND 
    (
        activity_seismo_info.ASI_EVENT_TIME>='2011-03-10 00:00:00' AND 
        activity_seismo_info.ASI_EVENT_TIME<='2011-03-17 23:59:59'
    ) 

ORDER BY activity_seismo_info.ASI_EVENT_TIME DESC
Run Code Online (Sandbox Code Playgroud)

查询的解释:

+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
| id | select_type | table   | type  | possible_keys             | key          | key_len | ref  | rows  | Extra                       |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+ 
|  1 | SIMPLE      | act...o | range | act...o_FI_1,act...o_FI_2 | act...o_FI_1 | 5       | NULL | 65412 | Using where; Using filesort |
+----+-------------+---------+-------+---------------------------+--------------+---------+------+-------+-----------------------------+
Run Code Online (Sandbox Code Playgroud)

使用:

PHP 5.2

MySQL 5.0.51a-3ubuntu5.4

推进 1.3

Symfony 1.2.5

ype*_*eᵀᴹ 27

我不这么认为。查询优化器应该足够聪明。

您可以尝试重新排列 WHERE 子句,并看到 EXPLAINS 在每种情况下都告诉您相同的情况。


关于可以做什么来优化这个查询:Is there an index on ASI_EVENT_TIME ?(这是我认为对于此查询最重要的,因为您还使用它对结果进行排序)。

其他两个字段(ASI_SEISMO_ID 和 ASI_ACTIVITY_ID)是否有索引?

如果您发布表格结构会有所帮助。


Gai*_*ius 16

文档

如果表具有多列索引,则优化器可以使用索引的任何最左边的前缀来查找行。例如,如果您在 (col1, col2, col3) 上有一个三列索引,则您在 (col1)、(col1, col2) 和 (col1, col2, col3) 上具有索引搜索功能。

如果列不构成索引的最左前缀,则 MySQL 不能使用索引。

所以是的,它应该与复合索引中列的顺序相同。

  • 如果表具有多列索引 _selecting_ 左侧的列很重要 - 但您选择的顺序无关紧要。因此,如果您有索引 a、b、c 并且您执行 `WHERE c = 'foo' AND a = 'bar' AND b = 'foobar'` 并且该索引仍然可以使用。 (4认同)

Mor*_*ker 10

不,没关系。

优化器在解析 SQL 后立即执行一系列简单的转换——这就是其中之一。


Ric*_*mes 8

哪里 foo 和 bar

优化与

WHERE 酒吧和 foo

然而,

WHERE 不相等#1 AND 不相等#2

无法优化这两个部分。例如,

其中 a 介于 1 和 3 之间且 b > 17

不能很好地利用 INDEX(a,b) 或 INDEX(b,a)

换一种说法,首先使用 WHERE 子句中的任何“=”测试和“和”,然后可以处理一个非“=”(IN、BETWEEN、> 等)。可以有效优化的不超过一个。

您的查询有 3 个这样的子句。

事实证明,INDEX(EVENT_TIME) 可能是最有用的——它将有助于其中一个 AND,并且它可能用于避免 ORDER BY 的“文件排序”。

如果没有重复的行(为什么会有重复?),然后去掉 DISTINCT。这会导致更多的努力。

询问性能问题时,请提供 SHOW CREATE TABLE 和 SHOW TABLE STATUS。

更新... 较新的版本(例如 MySQL 5.7)在某些情况下IN( list of constants )几乎可以像=. 为了安全起见,请坚持以下顺序(每个部分都是可选的):

  1. 任意数量的=.
  2. 一些INs
  3. 最多一个范围。