2013-01-16 23 views
0

我在应用程序中实现了一个排行榜,我想每隔几次更新一次。 对于我创造了排行榜的两个表,每一个看起来是这样的:用低成本CPU进行MySql更新

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数量,我不在乎更新会花费更长的时间。

我该怎么做?

回答

0

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

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

此外,没有必要从每行返回得分值以获得排行榜表中所有行的锁定。该SELECT语句的ORDER BY也可能正在占用CPU周期(如果存在与没有索引3210作为主要专栏。不必要的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 ; 
+0

TNX帮我提高性能一点,但q问题是如何减少CPU,因为时间几乎没有改变,所以它的CPU。 –