SQL性能UNION与OR
我刚刚阅读了一篇优化文章的一部分,并在以下声明中进行了细分 :
当使用
OR
replace语句使用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';
从一个快速的解释:
使用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');
在几乎所有情况下, union
或union all
版本都将对用户表进行两次全表扫描。
这个版本在实践中要好得多,因为它只会扫描一次表格。 如果可用的话,它也将只使用索引一次。
原来的陈述似乎是错误的,几乎所有的数据库和任何情况。
比尔·卡尔文的回答是非常正确的。 当OR语句的两个部分都有自己的索引时,联合会更好,因为一旦有一小部分结果,就可以更容易地sorting并消除重复。 总成本几乎要比仅使用一个索引(对于其中一列)和对另一列使用表扫描(因为mysql仅对一列使用一个索引)要低。
这取决于桌子的结构和需要,但是在大桌子上,联盟给了我更好的结果。