MySQL 中的 UNION ALL 和 LIMIT
Posted
技术标签:
【中文标题】MySQL 中的 UNION ALL 和 LIMIT【英文标题】:UNION ALL and LIMIT in MySQL 【发布时间】:2010-10-24 13:45:25 【问题描述】:假设我要执行这个查询:
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION ALL
(SELECT a FROM t2 WHERE a=11 AND B=2)
UNION ALL
(SELECT a FROM t3 WHERE a=12 AND B=3)
ORDER BY a LIMIT 1000;
如果“t1”中有 550 个结果可用,“t2”中有 450 个结果可用,mysql 是否足够聪明,可以跳过“t3”?
我正在查看 MySQL 文档 (http://dev.mysql.com/doc/refman/5.1/en/union.html),但似乎找不到答案。
【问题讨论】:
【参考方案1】:目前,即使前几个查询中有足够的行,MySQL 也会在联合上执行所有选择,正如@Yuki Inoue 在他们的回答中提到的那样。使用@user1477929 的答案,您可以将查询重写为:
(SELECT a FROM t1 WHERE a=10 AND B=1 LIMIT 1000)
UNION ALL
(SELECT a FROM t2 WHERE a=11 AND B=2 LIMIT 1000)
UNION ALL
(SELECT a FROM t3 WHERE a=12 AND B=3 LIMIT 1000)
ORDER BY a LIMIT 1000;
这将给你最多 1000 行,并且永远不会扫描超过 3000 行。
【讨论】:
如果ORDER BY a LIMIT 500,1000
会发生什么? Mysql 从三个表中创建具有 3000 个结果(最大)的临时表,然后从临时表中获取第 501 行?还是别的什么?【参考方案2】:
它适用于我,我正在使用 MySQL。
但要确保所有人的限制数量始终相同
在该示例中,它会从每个表中为您提供 3 个结果
(SELECT a FROM t1 WHERE a=10 AND B=1 LIMIT 9)
UNION ALL
(SELECT a FROM t2 WHERE a=11 AND B=2 LIMIT 9)
UNION ALL
(SELECT a FROM t3 WHERE a=12 AND B=3 LIMIT 9)
【讨论】:
【参考方案3】:如果你有一个非常大的表,那么你可以执行下面的查询来看看 MySQL 优化器有多聪明......
(
select * from very_large_table
union all
select * from very_large_table
) limit 1
遗憾的是,与以下查询相比,此查询需要很长时间。
select * from very_large_table limit 1
似乎每当需要UNION
的结果时,MySQL都会首先计算UNION结果的整个临时表。
版本
MySQL 8.0.11【讨论】:
【参考方案4】:在 UNION 语法描述 (http://dev.mysql.com/doc/refman/5.1/en/union.html) 中指定:
UNION 的默认行为是 重复的行被从 结果。可选的 DISTINCT 关键字 除了默认值之外没有任何影响 因为它还指定 重复行删除。随着 可选 ALL 关键字,重复行 删除不会发生,结果 包括所有匹配的行 SELECT 语句。
我想,这就是你问题的答案。
【讨论】:
在结果集中,来自 t1 的数据是否总是在 t2 和 t3 之前,而 t2 在 t3 之前?我需要读取按“B ASC”排序的数据,并想知道是否可以跳过联合后的“按 B ASC 排序”。 在手册中指定,“UNION 默认会产生一组无序的行”,所以据我了解,不能保证。 @Kel 请告知如果第一次使用LIMIT 0,5
并在第二次查询时会发生什么,例如LIMIT 5,10
?无序的行集,但我希望LIMIT 5,10
不会有LIMIT 0,5
的行?无序,但我希望所有查询的顺序相同?
正如我测试的sqlfiddle.com/#!9/09b72b/6 似乎UNION
总是创建具有相同结果顺序的临时表。并且使用不同的LIMIT
我将获得唯一(不重复)的结果。【参考方案5】:
是的,如果从t1
和t2
返回的结果等于LIMIT
,MySql 足够聪明,可以跳过t3
。事实上,这是默认行为。
【讨论】:
以上是关于MySQL 中的 UNION ALL 和 LIMIT的主要内容,如果未能解决你的问题,请参考以下文章