我有带有以下字段的表: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')
并且如果我的用户数量很少,那么效果很好,但是如果用户表包含的行数超过10万行,此查询将执行超过50秒。
请您给我答案或想法,我可以如何提高此简单查询的速度。
谢谢!
当前,NOT IN
查询正在触及整个100,000行。让我们通过更改查询和架构来避免这种情况。让我们设计一种方法,而不是为所有用户设置is_online
,只需要触摸当前在线的用户。
不是让is_online
为布尔值,而是让它为DATETIME
或BIGINT
。然后将其设置为在线的新值,而忽略其他值。
这将需要其他信息-新的高价值。只需将其存储在具有单行单列的另一个表中。
此架构避免了注释中的时间戳错误。唯一“在线”的用户是具有is_online
中最新值的用户。其他所有离线。
现在让我们检查其余的架构。您确实需要id
和username
吗?投掷id
,使username
为PRIMARY 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;