为什么MySQL挂在这个简单的子查询上?

为什么MySQL挂在这个简单的子查询上?,mysql,sql-update,subquery,query-optimization,Mysql,Sql Update,Subquery,Query Optimization,我有一个简单的查询,它运行大约5秒钟,返回大约500条记录,但是为什么我要在复合语句MySQL中使用它,这个问题还没有解决 SELECT DISTINCT ARTIST_ID FROM WORK GROUP BY ARTIST_ID HAVING AVG(WORK_MILLIS_VIEWED) > 10 然而,下面的查询从未终止。根据进程列表,它只是创建一个临时表,尽管它的运行时间应该只比子查询稍长,因为艺术家表非常小 SELECT ARTIST_NAME FROM AR

我有一个简单的查询,它运行大约5秒钟,返回大约500条记录,但是为什么我要在复合语句MySQL中使用它,这个问题还没有解决

SELECT DISTINCT ARTIST_ID FROM WORK
    GROUP BY ARTIST_ID
    HAVING AVG(WORK_MILLIS_VIEWED) > 10
然而,下面的查询从未终止。根据进程列表,它只是创建一个临时表,尽管它的运行时间应该只比子查询稍长,因为艺术家表非常小

SELECT ARTIST_NAME FROM ARTIST
    WHERE ARTIST_ID IN (SELECT DISTINCT ARTIST_ID
         FROM WORK GROUP BY ARTIST_ID
         HAVING AVG(WORK_MILLIS_VIEWED) > 10)

我犯了愚蠢的错误吗?数据库似乎没有做任何其他事情。

MySQL很难在WHERE子句中使用子查询。它通常决定多次运行子查询(对于与子查询比较的每个不同的ARTIST_ID值,运行一次),即使您知道并且我知道子查询不会更改

解决方法是在FROM子句中运行子查询并连接到该子查询:

SELECT A.ARTIST_NAME 
FROM (
    SELECT ARTIST_ID FROM WORK 
    GROUP BY ARTIST_ID HAVING AVG(WORK_MILLIS_VIEWED) > 10
) AS T
JOIN ARTIST A ON A.ARTIST_ID = T.ARTIST_ID
这将至少运行子查询一次,并在子查询连接到另一个表实例时将其存储在临时表中


您还将受益于按此顺序排列的一对列的索引
(艺术家ID,作品\u MILLIS\u已查看)

啊,我明白了,所以MySQL正在重复聚合查询,这大约需要500x5s-但我可以更改隔离级别,它就会消失。@awiebe-让我们知道隔离级别是否有这种效果。@Rick James-仔细看,似乎我可以更改隔离级别,因为我的数据库不活动,这对我的应用程序有效,但对其他应用程序不好。在这种情况下,最好的办法是在子查询表上获取一个锁。好的,最后,我使用了表锁,将统计数据拉入我的业务逻辑,然后将它们放回带有更新的Artister中。此操作对事务存储引擎不起作用,因此您最好暂时挂起事务—快速运行批处理作业、更新,然后解锁。