MySQL在子查询性能方面表现怪异

MySQL在子查询性能方面表现怪异,mysql,sql,query-optimization,Mysql,Sql,Query Optimization,我在RESTAPI端点上遇到了一个奇怪的beahviour。基本上我有两个表,一个带有id和其他相关字段的用户表,一个带有uid(映射用户id)和其他几个字段的操作表 我想提取执行特定操作的用户,我正在执行以下操作: SELECT * FROM users where id IN (select uid from action WHERE [CONDITIONS] order by [CRITERIA]); 考虑到我的数据库的大小,这个查询运行大约需要两秒钟,这对于我的用例来说是完全不可接受的

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

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

SELECT * FROM users where id IN (select uid from action WHERE [CONDITIONS] order by [CRITERIA]);
考虑到我的数据库的大小,这个查询运行大约需要两秒钟,这对于我的用例来说是完全不可接受的

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

select uid from action WHERE [CONDITIONS] order by [CRITERIA];
手动连接要由IN运算符匹配的字符串后执行:

SELECT * FROM users where id IN [MANUAL CONCAT];
这两个查询都在同一个数据集上以5ms的速度运行

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

更新

如果我只是简单地使用一个连接(见下面的代码),速度会快很多(大约10毫秒),但我仍然不知道IN在这里是如何工作的

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

我怀疑,实际上匹配的行大约是5-10行(共5行)。

首先,中
排序是没有用的,因此您可以在没有
排序的情况下重写它

其次,
存在
通常比
中的
快:

SELECT u.*
FROM users u
WHERE EXISTS (SELECT 1 FROM action a WHERE a.uid = u.id and [CONDITIONS]);
为了获得最佳性能,您需要在
操作(uid,…)
上设置索引。
用于(选择…
中的
[条件]

所需的其他列。
的优化效果非常差-
SELECT
被重复评估

在某些新版本中,
SELECT
将具体化,并将自动生成
索引。不过,
JOIN
很可能会继续更快


查看
解释选择…
;它可能会提供一些正在(或不正在)发生的事情的线索。如果您想进一步讨论,请提供表的完整
选择
显示创建表

存在更快,但没有区别。在没有任何缓存的情况下,第一个查询的平均执行时间为2.10秒,最大执行时间为1.95秒。我将添加索引,但我仍然不明白如何使两个不同的查询更快。您看到的性能表明,条件在优化中起着非常重要的作用。