Mysql SQL性能联合vs或
我刚刚读了一篇优化文章的一部分,并对以下语句进行了解释: 使用SQL时,请将使用Mysql SQL性能联合vs或,mysql,sql,performance,union,Mysql,Sql,Performance,Union,我刚刚读了一篇优化文章的一部分,并对以下语句进行了解释: 使用SQL时,请将使用或的语句替换为联合: 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’; 从快速的解释中: 使用或: 使用联合:
或的语句替换为联合
:
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’;
从快速的解释中
:
使用或:
使用联合
:
select username from users where company = ‘bbc’ or company = ‘itv’;
这不是意味着工会的工作加倍了吗
虽然我认为对于某些RDBMS和某些表模式,UNION
可能更有效,但这并不像作者建议的那样绝对正确
问题:
我错了吗?这不是同一个问题
我对MySQL没有太多经验,因此我不确定查询优化器做什么或不做什么,但以下是我的一般背景(主要是ms sql server)的想法
通常,查询分析器可以接受上述两个查询,并对它们做出完全相同的计划(如果它们是相同的),因此这并不重要。我怀疑这些查询之间没有性能差异(它们是等效的)
及
现在,问题是,下面的查询之间会有区别吗?我实际上不知道,但我怀疑优化器会使它更像第一个查询
select username from users where company = ‘bbc’ or company = ‘itv’;
及
这取决于优化器根据数据大小、索引、软件版本等最终执行的操作
我想使用OR会让优化器有更好的机会找到一些效率,因为一切都在一个逻辑语句中
此外,联合也有一些开销,因为它创建了一个重置集(没有重复项)。
如果公司被编入索引,联合体中的每一条语句都应该很快执行。。。不确定它真的能做双倍的工作
底线
除非你真的迫切需要从你的查询中挤出每一点速度,否则最好只使用最能传达你意图的表单。。。手术室
更新
我还想在这里提一下。我相信以下查询将提供比OR更好的性能(这也是我更喜欢的形式):
从公司所在的用户中选择用户名(“bbc”、“itv”)
在几乎所有情况下,union
或union-all
版本将对用户表进行两次完整的表扫描
实际上,或
版本要好得多,因为它只扫描表一次。它还将只使用一次索引(如果可用)
对于任何数据库和任何情况,最初的陈述似乎都是错误的。要么你读的文章使用了一个不好的例子,要么你误解了他们的观点
select username from users where company = 'bbc' or company = 'itv';
这相当于:
select username from users where company IN ('bbc', 'itv');
MySQL可以使用company
上的索引进行此查询。没有必要做任何联合
更棘手的情况是,您的或
条件涉及两个不同的列
假设在公司
上有一个索引,在城市
上有一个单独的索引。鉴于MySQL通常在给定查询中每个表只使用一个索引,它应该使用哪个索引?如果它使用company
上的索引,它仍然需要进行表扫描以查找city
位于伦敦的行。如果它使用city
上的索引,则必须对company
为bbc的行进行表扫描
UNION
解决方案适用于这种情况
select username from users where company = 'bbc'
union
select username from users where city = 'London';
现在,每个子查询都可以使用索引进行搜索,子查询的结果由联合组合而成
一位匿名用户建议对我的上述答案进行编辑,但主持人拒绝了编辑。应该是评论,而不是编辑。建议的编辑声明是UNION必须对结果集进行排序以消除重复行。这会使查询运行变慢,因此索引优化是一个清洗过程
我的回答是,索引有助于在联合之前将结果集减少到少量行。UNION实际上消除了重复项,但要做到这一点,它只需对小的结果集进行排序。在某些情况下,where子句可能与表的很大一部分匹配,并且在联合过程中进行排序与简单地进行表扫描一样昂贵。但更常见的情况是,通过索引搜索减少结果集,因此排序的成本比表扫描低得多
差异取决于表中的数据和搜索的术语。确定给定查询的最佳解决方案的唯一方法是在中尝试这两种方法并比较它们的性能。Bill Karwin的答案非常正确。当OR语句的两个部分都有自己的索引时,最好进行并集,因为一旦有了一小部分结果,就更容易对它们进行排序并消除重复项。总成本几乎比只使用一个索引(针对一列)和表扫描(针对另一列)要低(因为mysql只针对一列使用一个索引)
它通常取决于表的结构和需求,但在大型表中,union给了我更好的结果。我认为union需要做更多的工作,因为它需要删除重复项,而过滤器将获取指定的条件。我很惊讶,它不建议在
中使用。如果mysql在WHERE
子句中有或
时不能使用索引,这可能是真的。@Igor Romanchenko,用一个答案来支持这一点。我猜查询分析器会将OR语句重新写入IN语句,因为它们是equivalent@Darren科普,我敢肯定是相反的。至少在MySQL中是这样。+关于不同的查询。尽管如此,UNION-ALL
仍然产生与UNION
相同的EXPLAIN
,UNION-ALL
通常比UNION
快。后者意味着UNION DISTINCTselect username from users where company IN ('bbc', 'itv');
select username from users where company = 'bbc' or city = 'London';
select username from users where company = 'bbc'
union
select username from users where city = 'London';