我如何使用“ WHERE NOT IN(…超过1000个项目…)”来优化更新SQL查询?

问题描述 投票:0回答:1

我有带有以下字段的表: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')

并且如果我的用户数量很少,那么效果很好,但是如果用户表包含的行数超过10万行,此查询将执行超过50秒。

请您给我答案或想法,我可以如何提高此简单查询的速度。

谢谢!

mysql sql query-performance
1个回答
0
投票

当前,NOT IN查询正在触及整个100,000行。让我们通过更改查询和架构来避免这种情况。让我们设计一种方法,而不是为所有用户设置is_online,只需要触摸当前在线的用户。

不是让is_online为布尔值,而是让它为DATETIMEBIGINT。然后将其设置为在线的新值,而忽略其他值。

这将需要其他信息-新的高价值。只需将其存储在具有单行单列的另一个表中。

此架构避免了注释中的时间戳错误。唯一“在线”的用户是具有is_online中最新值的用户。其他所有离线。

现在让我们检查其余的架构。您确实需要idusername吗?投掷id,使usernamePRIMARY KEY;这样可以加快处理速度,因为它不必进行双重查找-首先找到具有给定用户名的ID,其次进入UPDATE行。 (注意:如果它是另一个表中的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;
© www.soinside.com 2019 - 2024. All rights reserved.