当UNION在SQL查询中停止优于OR条件时?

时间:2018-01-25 08:44:30

标签: mysql sql query-performance

在大多数情况下,当我尝试删除OR条件并用UNION(分别保存每个条件)替换它们时,它表现得更好,因为查询的那些部分可以再次索引。

当这个“技巧”停止有用时,是否有经验法则(可能还有一些支持它的文档)?它对2 OR条件有用吗? 10 OR条件?随着UNION数量的增加,UNION的不同部分可能会有自己的开销。

你对此有什么经验法则?

转型的一个小例子:

SELECT 
    a, b
FROM
    tbl
WHERE
    a = 1 OR b = 2

转换为:

(SELECT 
    tbl.a, tbl.b
FROM
    tbl
WHERE
    tbl.b = 2) 
UNION DISTINCT 
(SELECT 
    tbl.a, tbl.b
FROM
    tbl
WHERE
    tbl.a = 1)

1 个答案:

答案 0 :(得分:1)

我建议没有有用的经验法则(RoT)。这就是为什么......

  • 正如您所暗示的,更多UNIONs意味着工作更慢,而更多ORs则不会(至少不是很多)。联盟的SELECTs代价很高,因为它们是分开的。我估计UNION N SELECTs需要大约N + 1或N + 2个时间单位,其中一个索引SELECT占用1个单位时间。相比之下,多个ORs几乎不会减慢查询速度,因为获取表的所有行是代价高昂的部分。

  • SELECT的每个UNION的运行速度取决于索引的好坏以及获取的行数。这可能会有很大差异。 (因此,很难设计出RoT。)

  • UNION首先生成一个临时表,每个SELECT添加它找到的行。这是一些开销。在较新的版本(5.7.3 / MariaDB 10.1)中,可以避免临时表的情况有限。 (这消除了假设的+1或+2,从而增加了设计RoT的复杂性。)

  • 如果是UNION DISTINCT(默认值)而不是UNION ALL,则需要进行重复数据删除传递,可能涉及临时表的排序。注意:这意味着即使是新版本也无法避免临时表。 UNION DISTINCT正好模仿OR,但可能知道ALL会给出相同的答案。