SQL Performance UNION vs OR

Jas*_*ary 63 mysql sql performance union

我刚才读的优化文章的一部分,segfaulted以下声明:

当使用SQL代替using语句ORUNION:

select username from users where company = ‘bbc’ or company = ‘itv’;
Run Code Online (Sandbox Code Playgroud)

至:

select username from users where company = ‘bbc’ union
select username from users where company = ‘itv’;
Run Code Online (Sandbox Code Playgroud)

从快速EXPLAIN:

使用OR:

在此输入图像描述

使用UNION:

在此输入图像描述

没有这意味着UNION确实在双工作

虽然我感谢UNION某些RDBMS和某些表模式的性能可能更高,但这并非如作者建议那样明确.

我错了吗?

Bil*_*win 96

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

select username from users where company = 'bbc' or company = 'itv';
Run Code Online (Sandbox Code Playgroud)

这相当于:

select username from users where company IN ('bbc', 'itv');
Run Code Online (Sandbox Code Playgroud)

MySQL可以company为此查询使用索引就好了.没有必要做任何UNION.

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

select username from users where company = 'bbc' or city = 'London';
Run Code Online (Sandbox Code Playgroud)

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

UNION解决方案是对于这种类型的箱子.

select username from users where company = 'bbc' 
union
select username from users where city = 'London';
Run Code Online (Sandbox Code Playgroud)

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


一位匿名用户建议对我上面的答案进行编辑,但主持人拒绝了编辑.它应该是评论,而不是编辑.建议编辑的主张是UNION必须对结果集进行排序以消除重复的行.这使查询运行速度变慢,因此索引优化是一个重要的问题.

我的回答是索引有助于在UNION发生之前将结果集减少到少量行.UNION实际上确实消除了重复,但要做到这一点,它只需要对小结果集进行排序.可能存在WHERE子句与表的重要部分匹配的情况,并且在UNION期间的排序与仅执行表扫描一样昂贵.但是通过索引搜索减少结果集更常见,因此排序比表扫描成本低得多.

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

  • 我提供的引用正是文章中的示例。所以没有什么可误解的。我知道使用“UNION”与“OR”**不是绝对正确的**。但我将其标记为正确,因为它将原始示例描述为“不正确”,同时提供了作者可能“意思”的用例。 (2认同)

Dar*_*opp 5

那些查询不一样.

我没有太多的MySQL经验,所以我不确定查询优化器做了什么或不做什么,但这是我的一般背景(主要是ms sql server)的想法.

通常情况下,查询分析器可以采用上述两个查询并从中生成完全相同的计划(如果它们是相同的),因此无关紧要.我怀疑这些查询之间没有性能差异(相当于)

select distinct username from users where company = ‘bbc’ or company = ‘itv’;
Run Code Online (Sandbox Code Playgroud)

select username from users where company = ‘bbc’ 
union
select username from users where company = ‘itv’;
Run Code Online (Sandbox Code Playgroud)

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

select username from users where company = ‘bbc’ or company = ‘itv’;
Run Code Online (Sandbox Code Playgroud)

select username from users where company = ‘bbc’ 
union all
select username from users where company = ‘itv’;
Run Code Online (Sandbox Code Playgroud)