我如何使用 "WHERE NOT IN (...more than 1000 items...)" 优化更新 SQL 查询?

How can i optimize update SQL query with "WHERE NOT IN (...more than 1000 items...)"?

我有 table 个字段:IDUSERNAMEDATAIS_ONLINE。每分钟我都会收到来自远程服务器的大量新数据,其中包含当前在线用户 [(username, is_online, data), ...]

我只需要为这个数组中的用户设置 IS_ONLINE = 1,为其他用户设置 IS_ONLINE = 0。 在循环中,我进行查询 UPDATE users SET is_online = 1, data = 'data' WHERE username = 'username'。然后到集合 IS_ONLINE = 0 我执行这个查询:

update users set is_online = 0 where username not in ('user1', 'user2', ... , 'user1000')

如果我有少量用户,它工作得很好,但如果用户 table 包含超过 10 万行,这个查询执行超过 50 秒。

请给我答案或想法如何提高这个简单查询的速度。

谢谢!

目前,NOT IN 查询涉及全部 100,000 行。让我们通过更改查询和模式来避免这种情况。与其为所有用户设置 is_online,不如设计一种方法,让您只需触摸那些 当前 在线的用户。

与其让 is_online 成为布尔值,不如将其设为 DATETIMEBIGINT。然后为那些在线的人设置一个新的、更高的值,忽略其他人。

这还需要一点信息 -- 新的高值。只需将它存储在另一个 table 中,单行单列。

此模式避免了评论中的时间戳混乱。唯一 "online" 的用户是 is_online 中最新值的用户;其他人都离线。

现在让我们检查架构的其余部分。 idusername 真的都需要吗?抛出id,使username成为PRIMARY KEY;这将加快速度,因为它不必进行双重查找——首先找到 id,给定用户名,其次到达 UPDATE 所在的行。 (注意:如果它是来自另一个 table 的 FOREIGN KEY,则可能会出现问题。如果是,请提供更多详细信息。)

另一个提示 -- 使用 1000 个语句来处理 1000 行比使用单个查询要慢很多。要对不同值进行多次更新,请使用 IODKU。

我希望这一切都可以归结为 3 sql 个语句:

BEGIN;
$hv = SELECT high_value FROM HighValue FOR UPDATE;
$hv++;
INSERT INTO MainTable
    VALUES
        ('user1', 'blah1', $hv),
        ('user2', 'blah2', $hv),
        ...
    ON DUPLICATE KEY UPDATE 
        data = VALUES(data),   -- sets the new `data` value
        is_online = $hv ;
UPDATE HighValue SET high_value = $hv;
COMMIT;