我刚刚在以下声明中阅读了优化文章的一部分和 segfaulted :
使用带有
OR
的{{1}}的SQL替换语句: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
:
这是不是意味着{em}在工作中加倍了?
虽然我感谢UNION
对于某些RDBMS和某些表模式可能更具性能,但这不是断然为真作为作者的建议。
我错了吗?
答案 0 :(得分:83)
您阅读的文章使用了一个不好的例子,或者您错误地解释了他们的观点。
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
组合。
匿名用户建议对我上面的回答进行编辑,但主持人拒绝了编辑。它应该是评论,而不是编辑。建议编辑的主张是UNION必须对结果集进行排序以消除重复的行。这使得查询运行速度变慢,因此索引优化是一种清洗。
我的回答是索引有助于在UNION发生之前将结果集减少到少量行。 UNION实际上确实消除了重复,但要做到这一点,它只需要对小结果集进行排序。可能存在WHERE子句与表的重要部分匹配的情况,并且在UNION期间的排序与仅执行表扫描一样昂贵。但是通过索引搜索减少结果集更常见,因此排序的成本远低于表扫描。
差异取决于表格中的数据和搜索的术语。确定给定查询的最佳解决方案的唯一方法是尝试the MySQL query profiler中的两种方法并比较它们的性能。
答案 1 :(得分: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 :(得分:2)
这取决于优化器最终根据数据大小,索引,软件版本等进行的操作。
我猜想使用OR可以让优化器更有机会找到一些效率,因为所有内容都在一个逻辑语句中。
此外,UNION还有一些开销,因为它会创建一个重置 set (没有重复项)。 如果将公司编入索引,UNION中的每个语句都应该很快执行...不确定它是否真的在做 double 工作。
除非你真的迫切需要从你的查询中挤出一点速度,否则最好只选择最能表达你意图的表格...... OR
我也想提到IN。我相信以下查询将提供比OR更好的性能(它也是我喜欢的形式):
select username from users where company in ('bbc', 'itv');
答案 3 :(得分:-1)
几乎在所有情况下,union
或union all
版本都会对users表执行两次全表扫描。
or
版本在实践中要好得多,因为它只会扫描一次表格。如果可用的话,它也只使用一次索引。
对于任何数据库和任何情况,原始陈述似乎都是错误的。
答案 4 :(得分:-1)
这取决于表的结构和需求,但在大表中,union给了我更好的结果。