繁体   English   中英

为什么 MySQL 中的 UNION 查询如此之慢?

[英]Why are UNION queries so slow in MySQL?

当我优化我的 2 个单个查询以在不到 0.02 秒内运行,然后UNION它们时,结果查询需要超过 1 秒才能运行。 此外, UNION ALLUNION DISTINCT花费的时间更长。

我认为允许重复会使查询运行得更快而不是更慢。 我真的只是更好地分别运行 2 个查询吗? 我更喜欢使用UNION

作为一个简单的例子,如果我这样做

SELECT name FROM t1 WHERE field1 = true

需要 0.001 秒

如果我这样做

SELECT name FROM t1 WHERE field1 = false

它需要 0.1 秒。

如果我然后跑

SELECT name FROM t1 WHERE field1 = true 
UNION ALL 
SELECT name FROM t1 WHERE field1 = false

它需要超过 1 秒。

当我优化我的 2 个单个查询以在不到 0.02 秒的时间内运行,然后将它们合并时,结果查询需要超过 1 秒才能运行。

您的查询是否包括ORDER BY … LIMIT子句?

如果将ORDER BY … LIMIT放在UNION ,它将应用于整个UNION ,并且在这种情况下不能使用索引。

如果id是主键,则此查询将是即时的:

SELECT  *
FROM    table
ORDER BY id
LIMIT 1

,但这个不会:

SELECT  *
FROM    table
UNION ALL
SELECT  *
FROM    table
ORDER BY id
LIMIT 1

此外, UNION ALLUNION DISTINCT花费的时间更长。 我认为允许重复会使查询运行得更快而不是更慢。

这似乎也是由于ORDER BY 对较小的集合进行排序比对较大的集合进行排序要快。

我真的只是更好地分别运行 2 个查询吗? 我更喜欢使用UNION

您需要对结果集进行排序吗?

如果没有,只需去掉最后的ORDER BY

关于UNION

  • UNION DISTINCT (在默认UNION )必然是慢,因为它必须收集两个结果,然后去重复。 但是,由于退回给客户的数量较少,因此可能会有一些补偿。
  • 直到最近的版本,所有UNIONs涉及一个临时表来收集结果,因此UNION必然比两个单独的SELECTs慢。 最近,(MySQL 5.7,MariaDB 10.1)对UNION ALL一些情况进行了改进,将数据从一个SELECT直接传送到客户端,然后再传送其他。
  • SELECT .. UNION SELECT .. ORDER BY ..等价于
    (SELECT .. UNION SELECT ..) ORDER BY .. -- 这个
    (SELECT ..) UNION (SELECT .. ORDER BY ..) -- 不是这个
    建议始终在每个SELECT周围使用括号。
  • 排序(通过ORDER BY可能需要额外的时间来处理它所附加的任何(选择或联合)。 不太可能更少的时间。 简单地说,优化器的目标是做任何最快的事情,这可能会被排序。
  • 所有这些声明都适用于 InnoDB; 不太受支持的 MyISAM 可能缺少一些最近的优化。
  • 有时,带有OR的单个SELECT可以通过将其转换为UNION来加速,从而允许使用两个索引。

关于测试:

  • 0.001 的时间闻起来就像您之前运行过查询并且结果缓存在“查询缓存”中。 通过关闭 QC 或添加SQL_NO_CACHE避免这种SQL_NO_CACHE
  • 选择WHERE flag = true (or false)有几种情况: flag是否被索引? flag几乎总是这些值之一吗? 这种情况下,将使用索引,并且可能比其他情况更快。
  • 如果你不同意我的任何陈述,请提供一个相反的例子。

猜测:由于您查询具有 2 个联合的一个表,因此 mysql 可能难以决定该表的锁定策略,或者它尝试进行一些缓存,这在这里不起作用,因为您查询不相交的集合,尝试多线程访问(非常合理)但遇到一些锁定/并发/文件搜索问题..

工会通常也可能采用更高的安全设置,因为这两个选择必须一致。 如果您将它们放入单独的事务中,则它们不会。

实验:制作表格的副本并将它们合并。 如果我是对的,它应该更快。

可能的解决方案:将单个文件拆分为多个文件,以实现更好的并发策略。 这不会/不应该有助于解决锁定问题,但排除了数据库中的多线程/搜索问题。

了解您使用的存储引擎会很有用。

好吧,只是我的 2 美分。 现在无法在这里测试。

UNION ALL 比 UNION 快,因为普通的 UNION 期望在两个连接的数据集中有需要删除的重复项。 如果您可以(通过内部 WHERE 子句)确保没有重复项,那么最好使用 UNION ALL 并让数据库引擎优化内部选择。

对分组结果的结果使用 WHERE 子句成本太高,因为您操作的内部结果比您需要的要多。 此外,无法处理数据库引擎的优化——结果没有任何共同点。

查看此链接了解详情https://dzone.com/articles/performance-tip-for-tuning-sql-with-union

是不是您测量的是响应时间而不是检索所有数据的时间?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM