我正在运行查询以更新用户字段,如下所示:

UPDATE Members SET abc = abc + 1 where Members.id in (
SELECT DISTINCT(memberId) FROM Events WHERE Events.createdAt > "2017-08-06 13:10:00";

令人震惊的是,有大约500个成员,这个查询运行40秒。。。
所以分解:
SELECT DISTINCT(memberId) FROM Events WHERE Events.createdAt > "2017-08-06 13:10:00"

运行0.1秒,只有39行匹配。
会员总数只有大约500人。我不明白为什么要花那么长时间。。。我遗漏了什么吗?
我在用mysql 5.6运行RDS

最佳答案

尝试用exists替换:

UPDATE Members m
    SET abc = abc + 1
    WHERE EXISTS (SELECT 1
                  FROM events e
                  WHERE e.memberId = m.id AND
                        e.createdAt > '2017-08-06 13:10:00'
                 );

为了提高性能,需要在events(memberId, createdAt)上建立索引。
我猜MySQL对Members中的每一行都运行一次子查询。这与您的计时一致--0.1秒*~500行约为50秒,与40秒相差不远。
对于SELECTs,这是几个版本之前修复的。也许这个问题仍然存在于非SELECT查询中。
你也可以这样写:
UPDATE Members m JOIN
       (SELECT DISTINCT e.memberId
        FROM events e
        WHERE e.createdAt > '2017-08-06 13:10:00'
       ) e
       ON e.memberId = m.id
    SET abc = abc + 1 ;

这是否比exists版本快,取决于数据的特性。如果没有建议的指数,这可能会更快。

关于mysql - 40秒奇怪的SQL性能难题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45533029/

10-11 09:07