SQL 性能 UNION 与 OR

问题描述 投票:0回答:6

我刚刚阅读了优化文章的一部分,并且对以下声明进行了segfaulted

使用 SQL 时,将使用

OR
的语句替换为
UNION
:

select username from users where company = ‘bbc’ or company = ‘itv’;

至:

select username from users where company = ‘bbc’ union
select username from users where company = ‘itv’;

快速

EXPLAIN

使用

OR

enter image description here

使用

UNION

enter image description here

这不是意味着

UNION
双倍工作吗

虽然我欣赏

UNION
对于某些 RDBMS 和某些表模式可能会更高效,但这并不像作者建议的那样“绝对正确”。 问题

我错了吗?

mysql sql performance union
6个回答
156
投票

select username from users where company = 'bbc' or company = 'itv';

这相当于:

select username from users where company IN ('bbc', 'itv');

MySQL 可以使用 
company

上的索引来执行此查询。无需进行任何 UNION。

更棘手的情况是,您有一个

OR

条件,涉及两个

不同
列。 select username from users where company = 'bbc' or city = 'London';

假设 
company

上有一个索引,并且

city
上有一个单独的索引。鉴于 MySQL 通常在给定查询中每个表仅使用一个索引,那么它应该使用哪个索引?如果它使用
company
上的索引,它仍然需要进行表扫描来查找
city
是伦敦的行。如果它使用
city
上的索引,则必须对
company
为 bbc 的行进行表扫描。

UNION

解决方案适用于此类情况。

select username from users where company = 'bbc' 
union
select username from users where city = 'London';

现在每个子查询都可以使用索引进行搜索,并且子查询的结果由 
UNION

组合在一起。

    


5
投票

我对 MySQL 没有太多经验,所以我不确定查询优化器做什么或不做什么,但以下是我从我的一般背景(主要是 ms sql server)中得出的想法。

通常,查询分析器可以接受上述两个查询并从中制定完全相同的计划(如果它们相同),所以这并不重要。我怀疑这些查询之间没有性能差异(它们是等效的)

select distinct username from users where company = ‘bbc’ or company = ‘itv’;

select username from users where company = ‘bbc’ union select username from users where company = ‘itv’;

现在的问题是,以下查询之间是否存在差异,我实际上不知道,但我怀疑优化器会让它更像第一个查询

select username from users where company = ‘bbc’ or company = ‘itv’;

select username from users where company = ‘bbc’ union all select username from users where company = ‘itv’;



2
投票

我猜想使用 OR 会让优化器有更好的机会找到一些效率,因为一切都在一个逻辑语句中。

此外,UNION 有一些开销,因为它创建了一个重置

set

(无重复项)。 如果 company 被索引的话,UNION 中的每条语句应该会很快执行...不确定它是否真的会做 double 的工作。 底线

除非您确实迫切需要提高查询的速度,否则最好采用最能传达您意图的形式... OR

更新

我还想说IN。我相信下面的查询会比 OR 提供更好的性能(这也是我更喜欢的形式):

select username from users where company in ('bbc', 'itv');

    


0
投票
这是我的基准测试结果


使用 UNION 时 - 查询花费了
13.8699

检查行的主要选择类型 - 
247685
使用 OR 时 - 查询花费了 

0.0126

秒并且检查了主要行 选择类型 -

495371

MySQL 使用一个索引进行查询,因此当我们使用
or

时,MySQL 使用一个列索引并扫描整个表以查找另一列

另一部分工会同样的工作可以进行2次

这就是为什么 or 比 union 更快


-1
投票
union

union all
版本将对用户表进行两次全表扫描。

or

版本在实践中要好得多,因为它只会扫描表一次。如果可用的话,它也只会使用一次索引。


对于任何数据库和任何情况,原始声明似乎都是错误的。


-1
投票

这通常取决于表的结构和需求,但在大型表中,联合给了我更好的结果。

© www.soinside.com 2019 - 2024. All rights reserved.