MySQL IN 与子查询性能奇怪的行为

标签 mysql sql query-optimization

我在 REST API 端点上遇到了奇怪的行为。基本上我有两个表,一个带有 id 和其他相关字段的用户表,以及一个带有 uid(映射用户 id)和其他几个字段的操作表。

我想提取已执行特定操作的用户,我正在执行以下操作:

SELECT * FROM users where id IN (select uid from action WHERE [CONDITIONS] order by [CRITERIA]);

考虑到我的数据库大小,此查询运行时间约为两秒,这对于我的用例来说是完全 Not Acceptable 。

如果我将查询分成两个子查询,首先执行,就会出现奇怪的行为:

select uid from action WHERE [CONDITIONS] order by [CRITERIA];

比手动连接要由 IN 运算符执行的匹配的字符串之后:

SELECT * FROM users where id IN [MANUAL CONCAT];

这两个查询在同一数据集上运行时间均低于 5 毫秒。

我的理解(可能是错误的)是先执行子查询,然后再执行主查询。这是错的吗? MySQL 每次都会执行 IN 子查询吗?

更新

如果我只是使用连接(参见下面的代码)会快得多(大约 10 毫秒),但我仍然不明白 IN 在这里是如何工作的。

SELECT distinct * FROM users join action on users.id = action.uid where [CONDITIONS];

我怀疑实际匹配的行数大约为 5M 中的 5-10 个这一事实很重要。

最佳答案

IN ( SELECT ... ) 的优化非常差 - SELECT 被重复评估。

在某些新版本中,SELECT 将被具体化,并且 INDEX 将自动生成。尽管如此,JOIN 很可能会继续变得更快。

查看解释选择...;它可能会提供一些关于正在发生(或未发生)的事情的线索。如果您想进一步讨论,请提供表的EXPLAIN、完整的SELECTSHOW CREATE TABLE

关于MySQL IN 与子查询性能奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31300310/

相关文章:

mysql - 如何发现 RDBMS 中的关系?

php - 处理多个主机上的 PHP 站点 session 的最佳方法是什么?

sql - Flex/Sqlite 中的异步 DAO?

mysql - 从组的最大值中选择最小值

sql - 高效计算 SQL 中的重要术语

jquery - 非常大的 Prestashop MySQL 查询会导致大量数据库使用

mysql - 两个表,共有行,否则

php - 几天后如何将数据从一个表移动到另一个表

sql - 将 SQLite FTS3 与 INTEGER 列一起使用

mysql - 使用多个查询或 vs 联合多个查询,哪个会更快?