0

我正在我的应用程序中实现一个排行榜,我想每隔几次更新一次。为此,我创建了两张排行榜,每张都如下所示:

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 原始数据。我希望减少它占用的 CPU 量,我不在乎更新会花费更长的时间。

我怎样才能做到这一点?

4

1 回答 1

0

我建议您尝试添加 index ... ON leaderboard (score),以避免排序操作。我还建议您从 UPDATE 语句中删除不必要的 SELECT (但我不知道这是否会对性能产生影响,但在这种情况下 SELECT 关键字不是必需的。

排序操作肯定会使用一些 CPU。我不清楚 UPDATE 语句中的 SELECT 是否被优化器忽略,或者计划是否与那里的(不必要的?) SELECT 有所不同。(在该上下文中包含 SELECT 关键字的目的是什么?)

此外,不必从每一行返回得分值来获取排行榜表中所有行的锁定。该 SELECT 语句上的 ORDER BY 也可能消耗 CPU 周期(如果没有score作为前导列的索引。4M 行结果集的不必要准备也消耗 CPU 周期。

目前尚不清楚为什么需要使用 SELECT ... FOR 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 ;
于 2013-01-16T17:01:39.517 回答