SQL性能UNION与OR

我刚刚阅读了一篇优化文章的一部分,并在以下声明中进行了细分

当使用ORreplace语句使用ORUNION

 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'; 

从一个快速的解释:

使用OR

在这里输入图像说明

使用UNION

在这里输入图像说明

这是不是意味着UNION双重工作

虽然我很欣赏UNION可能对某些RDBMS和某些表模式更高性能,但这并不是作者的build议。

我错了吗?

您阅读的文章中使用了一个不好的例子,或者您误解了他们的观点。

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

这相当于:

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

MySQL可以使用这个查询的company索引就好了。 没有必要做任何联合。

更棘手的情况是你有一个OR条件涉及两个不同的列。

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

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

UNION解决scheme适用于这种情况。

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

现在,每个子查询都可以使用索引进行search,而子查询的结果由UNION组合。


一位匿名用户对我的回答提出了一个修改,但一位版主拒绝了这个修改。 它应该是一个评论,而不是一个编辑。 提议编辑的要求是UNION必须sorting结果集以消除重复的行。 这使得查询运行速度变慢,因此索引优化是一种洗涤。

我的回应是,在UNION发生之前,索引有助于将结果集减less到less数几行。 UNION实际上消除了重复,但要做到这一点,只需要对小的结果集进行sorting。 可能有些情况下,WHERE子句匹配表的重要部分,UNION中的sorting与简单地执行表扫描一样昂贵。 但是通过索引search来减less结果集更为常见,所以sorting比表扫描要便宜得多。

差异取决于表格中的数据和正在search的术语。 确定给定查询的最佳解决scheme的唯一方法是在MySQL查询分析器中尝试这两种方法,并比较它们的性能。

这些不是同一个查询。

我没有太多的MySQL经验,所以我不确定查询优化器做了什么或不做什么,但这里是我的一般背景(主要是MS SQL服务器)的想法。

通常情况下,查询分析器可以采取上述两个查询,并做出完全相同的计划(如果他们是相同的),所以没关系。 我会怀疑这些查询之间没有性能差异(相当于)

 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'; 

这取决于优化器最终根据数据大小,索引,软件版本等进行的操作。

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

此外,UNION有一些开销,因为它创build一个重置 (没有重复)。 如果公司被编入索引,UNION中的每个声明都应该执行得相当迅速……不确定是否真的在做两倍的工作。

底线

除非你真的有需要尽力挤出你的查询速度的每一个点,否则可能会更好的去与最好的沟通你的意图的forms… OR

更新

我也打算提到IN。 我相信下面的查询会比OR更好的performance(这也是我喜欢的forms):

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

在几乎所有情况下, unionunion all版本都将对用户表进行两次全表扫描。

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

原来的陈述似乎是错误的,几乎所有的数据库和任何情况。

比尔·卡尔文的回答是非常正确的。 当OR语句的两个部分都有自己的索引时,联合会更好,因为一旦有一小部分结果,就可以更容易地sorting并消除重复。 总成本几乎要比仅使用一个索引(对于其中一列)和对另一列使用表扫描(因为mysql仅对一列使用一个索引)要低。

这取决于桌子的结构和需要,但是在大桌子上,联盟给了我更好的结果。