我正在我的应用程序中实现一个排行榜,我想每隔几次更新一次。为此,我创建了两个排行榜表格,每个表格看起来像这样:
user_id, score, rank
下面是我的更新查询:
select score from leaderboard order by score for update;
select(@rankCounter := 0);
update leaderboard set rank = (select(@rankCounter := @rankCounter + 1)) order by score desc;
我正在使用我的活动表进行查询,并且每隔几次就切换一次活动表。
更新目前大约需要3分钟(在我的机器上)来更新4M个raws。我希望减少CPU的使用量,我不关心更新会花更长的时间。
我该怎么做呢?
发布于 2013-01-17 01:01:40
我建议您尝试添加一个索引... ON leaderboard (score)
,以避免排序操作。我还建议您从UPDATE语句中删除不必要的SELECT (但我不知道这是否对性能有影响,但SELECT关键字在该上下文中不是必需的。
排序操作肯定会使用一些CPU。我不清楚是优化器忽略了UPDATE语句中SELECT语句,还是计划与此不同(不必要?)在那里选择。(在该上下文中包含SELECT关键字的目的是什么?)
此外,没有必要从每一行返回分值来获得排行榜中所有行的锁。SELECT语句上的ORDER BY也可能消耗CPU周期(如果没有以score
作为前导列的索引)。不必要的4M行结果集的准备也会消耗CPU周期。
不清楚为什么有必要使用SELECT ...对于UPDATE,当UPDATE语句本身将获得必要的锁时。( SELECT ...FOR UPDATE语句将仅在BEGIN TRANSACTION上下文中或禁用自动提交的情况下获得锁。(这里我假设leaderboard
是一个InnoDB表。)
MySQL可以利用索引来避免排序操作:
CREATE INDEX leaderboard_IX1 ON leaderboard (score) ;
这应该足以更新排名列:
SET @rankCounter := 0;
UPDATE leaderboard
SET rank = @rankCounter := @rankCounter + 1
ORDER BY score DESC ;
https://stackoverflow.com/questions/14362304
复制相似问题