MySql用低成本CPU更新

时间:2013-01-16 15:47:28

标签: mysql sql-update ranking

我正在我的应用程序中实现一个排行榜,我想每隔几次更新一次。 为此,我创建了两个排行榜的表格,每个人都看起来像这样:

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数量,而且我不关心更新需要更长的时间。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

我建议您尝试添加索引... ON leaderboard (score),以避免排序操作。我还建议您从UPDATE语句中删除不必要的SELECT(但我不知道它是否有任何性能影响,但在该上下文中不需要SELECT关键字。

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

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

当UPDATE语句本身将获得必要的锁时,为什么必须使用SELECT ... FOR 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 ;