Jas*_*ary 63 mysql sql performance union
我刚才读的优化文章的一部分,segfaulted以下声明:
当使用SQL代替using语句
OR
有UNION
: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 select username from users where company = ‘itv’;
从快速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
,则必须对行进行表扫描,其中company
bbc为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查询分析器中尝试这两种方法并比较它们的性能.
那些查询不一样.
我没有太多的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)