如果条件之间存在OR,我应该如何创建索引?

时间:2016-06-08 20:56:28

标签: mysql sql

我有这样的查询:

DELETE FROM events WHERE type = 4 AND author_id IN (?, ?) AND post_id IN (?, ?)

如您所知,author_id IN (? , ?)转换为author_id = ? OR author_id = ?。那么我应该在author_id列上创建索引吗?

事实上,我正在尝试理解MySQL在它们之间存在OR时如何处理条件。我在某处读到了这句话:

  

MySQL遇到OR时似乎忽略了索引。

但我无法理解它的含义。有人可以吗?总的来说,上面的查询需要哪些索引?

1 个答案:

答案 0 :(得分:2)

OR通常会阻止有效使用索引,这是正确的。在处理WHERE子句时,查询通常只能为每个表使用一个索引。所以,如果你有像

这样的条件
WHERE col1 = 1 OR col2 = 2

它无法使用任何单个索引来查找所有匹配的行。您通常最好将查询拆分为两个并使用UNION

SELECT ...
FROM TABLE
WHERE col1 = 1
UNION
SELECT ...
FROM TABLE
WHERE col2 = 2

但是,我想我在某处读过,在简单的情况下,MySQL能够自动执行此转换。检查查询的EXPLAIN输出。

但是当OR条件涉及相同的列时,它仍然可以使用索引,例如如果你有

WHERE col1 = 1 OR col1 = 2

只需要在col1的索引中查找这两个索引条目。这就是你写作时的作用:

WHERE col1 IN (1, 2)

但是,您的查询比这更复杂,因为它还将多个条件与AND组合在一起。如果您只是使用=比较,它可以使用多列索引对其进行优化,例如

INDEX (type, author_id, post_id)

但如果您有多个IN条件,则无法完成此操作,因为它需要枚举所有组合。

type = 4 AND author_id IN (1, 2) AND post_id IN (10, 20)

需要查找所有这些索引:

4, 1, 10
4, 1, 20
4, 2, 10
4, 2, 20

我不认为MySQL会生成这样的所有组合(但我可能错了 - 检查EXPLAIN输出以查看是否可以。)

相反,它会选择它认为最有效的索引,使用它来查找与条件的那部分匹配的行,并扫描这些行以评估剩余条件。