我如何使用 "WHERE NOT IN (...more than 1000 items...)" 优化更新 SQL 查询?
How can i optimize update SQL query with "WHERE NOT IN (...more than 1000 items...)"?
我有 table 个字段:ID
、USERNAME
、DATA
和 IS_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
成为布尔值,不如将其设为 DATETIME
或 BIGINT
。然后为那些在线的人设置一个新的、更高的值,忽略其他人。
这还需要一点信息 -- 新的高值。只需将它存储在另一个 table 中,单行单列。
此模式避免了评论中的时间戳混乱。唯一 "online" 的用户是 is_online
中最新值的用户;其他人都离线。
现在让我们检查架构的其余部分。 id
和 username
真的都需要吗?抛出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;
我有 table 个字段:ID
、USERNAME
、DATA
和 IS_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
成为布尔值,不如将其设为 DATETIME
或 BIGINT
。然后为那些在线的人设置一个新的、更高的值,忽略其他人。
这还需要一点信息 -- 新的高值。只需将它存储在另一个 table 中,单行单列。
此模式避免了评论中的时间戳混乱。唯一 "online" 的用户是 is_online
中最新值的用户;其他人都离线。
现在让我们检查架构的其余部分。 id
和 username
真的都需要吗?抛出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;