我刚刚阅读了一篇优化文章的一部分,并对以下语句进行了分段错误:
当使用使用
OR的SQL语句时,使用一个UNION: 从公司=‘bbc’或公司=‘itv’的用户中选择用户名; 至: 从公司=‘bbc’联盟的用户中选择用户名,从公司=‘itv’的用户中选择用户名;
从快速的EXPLAIN
使用OR

使用UNION

这不意味着UNION的工作量增加了一倍吗
虽然我理解UNION对于某些RDBMSes和某些表模式可能具有更高的性能,但正如作者所建议的那样,这并不是绝对正确的。
问题
我说错了吗?
发布于 2012-12-13 18:35:40
要么你读的文章引用了一个糟糕的例子,要么你曲解了他们的观点。
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所在的行进行表扫描。
UNION解决方案是针对这种情况的。
select username from users where company = 'bbc'
union
select username from users where city = 'London';现在,每个子查询都可以使用索引进行搜索,子查询的结果由UNION组合。
一个匿名用户建议对我上面的答案进行编辑,但是版主拒绝了编辑。它应该是一个评论,而不是编辑。建议编辑的声明是,UNION必须对结果集进行排序,以消除重复的行。这使得查询运行得更慢,因此索引优化就是一次清洗。
我的反应是,索引有助于在UNION发生之前将结果集减少到少量行。UNION实际上消除了重复,但要做到这一点,它只需对小的结果集进行排序。在某些情况下,where子句与表的很大一部分匹配,而在UNION中进行排序就像简单地进行表扫描一样昂贵。但是,通过索引搜索来减少结果集是比较常见的,所以排序比表扫描成本低得多。
差异取决于表中的数据和正在搜索的术语。确定给定查询的最佳解决方案的唯一方法是在MySQL查询分析器中尝试这两种方法并比较它们的性能。
发布于 2012-12-06 19:07:19
这些不是相同的查询。
我对MySQL没有太多的经验,所以我不确定查询优化器做什么或不做什么,但是下面是我的一般背景(主要是MySQL)的想法。
通常情况下,查询分析器可以接受上述两个查询,并对它们制定完全相同的计划(如果它们是相同的),所以这并不重要。我怀疑这些查询(它们是等价的)之间没有性能差异。
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’;发布于 2012-12-06 19:07:25
这取决于优化器根据数据、索引、软件版本等的大小所做的事情。
我猜想使用OR会给优化器找到一些效率的更好机会,因为所有东西都在一个逻辑语句中。
同时,UNION也有一些开销,因为它创建了一个重置集(没有重复设置)。如果公司被编入索引,联盟中的每个语句都应该执行得很快.不确定它是否真的能做两倍的工作。
底线
除非你真的有迫切的需要挤出你的查询的每一点速度,它可能更好地与形式,最好是沟通你的意图.OR
更新
我也想提一下。我相信以下查询将提供比OR更好的性能(这也是我更喜欢的形式):
select username from users where company in ('bbc', 'itv');
https://stackoverflow.com/questions/13750475
复制相似问题