如何在MySQL和PHP中从500万行的记分牌中获得排名?
我有一个排行榜,其中有一个“得分”栏。我还在分数列上有一个索引,它允许我非常快速地按分数排序表格,甚至可以将前十名或任意数量的分数分割出来——即使有500万行 然而,我真正想要的是在排行榜上显示玩家的“排名”。我尝试过几种方法,但在处理超过100000行的数据时,似乎没有一种方法是有效的(它们开始占用超过半秒的时间,考虑到我预期当前有数百个用户,这太长了) 我目前正在使用以下查询来确定一个用户的排名,然后在我的输出中为高于这个排名的用户simlpy递增-但是速度非常慢如何在MySQL和PHP中从500万行的记分牌中获得排名?,php,mysql,database,ranking,Php,Mysql,Database,Ranking,我有一个排行榜,其中有一个“得分”栏。我还在分数列上有一个索引,它允许我非常快速地按分数排序表格,甚至可以将前十名或任意数量的分数分割出来——即使有500万行 然而,我真正想要的是在排行榜上显示玩家的“排名”。我尝试过几种方法,但在处理超过100000行的数据时,似乎没有一种方法是有效的(它们开始占用超过半秒的时间,考虑到我预期当前有数百个用户,这太长了) 我目前正在使用以下查询来确定一个用户的排名,然后在我的输出中为高于这个排名的用户simlpy递增-但是速度非常慢 SELECT tro.s
SELECT tro.score, tro.userId,
(
SELECT count(*)
FROM scoreboard tri
WHERE tri.score >= :score
) AS rank
FROM test_tracks tro
WHERE userId = :userID");
我正在考虑生成一个排名表,以“缓存”用户在向记分板插入新分数时的排名,但即使生成此表也需要很长的时间(分钟,可能数小时)
有人知道建立排名的好方法吗?最好我也能对结果进行分页,但即使只是暂时建立排名也足够了
提前谢谢 实现这一点的最佳方法是使用一个表,该表由一个时间表定期更新(一小时一次、一天一次等),该时间表可以花费更长的查询时间并运行它。没有必要总是用这些繁重的查询来破坏数据库。这还意味着长时间运行的查询每隔一段时间运行一次,而不是对每个浏览该页面的用户都运行一次
这里有一个很好的例子,总数每天更新一次。我最近对分数进行了排名。我将发布粗略的mysql代码,这将进一步指导您
SET @rank = 0, @prev_val = NULL;
SELECT id,rank, score FROM (
SELECT @rank := IF(@prev_val=score,@rank,@rank+1) AS rank,
@prev_val := score AS score, id
FROM rank ORDER BY score DESC
)AS result
其中,表名为“rank”,字段为id、score
希望这有帮助以下是我能提供的最好建议。(它在500万行上对我有效,但没有经过并发测试。出于某种原因,它在InnoDB中的运行速度非常慢,但在MyISAM表中的运行时间不到一秒,因此事务支持将丢失。) 我创建了一个名为ranks:ranks(score int PK,num int)的表 然后在上面撒上这个: 插入等级(分数,num)选择分数,按分数从玩家组中计数(*) 之后,我创建了以下存储过程:
DELIMITER $$
CREATE PROCEDURE testranks(
OldScore INT
,NewScore INT
)
BEGIN
INSERT INTO ranks (score,num) VALUES (NewScore,1)
ON DUPLICATE KEY
UPDATE num = num + 1;
UPDATE ranks SET num = num - 1 WHERE score = OldScore;
DELETE FROM ranks WHERE num = 0 AND score = OldScore;
SELECT COUNT(*) FROM ranks WHERE score >= newscore;
END$$
DELIMITER ;
如果您调用TestRanks(使用旧分数和新分数),它将返回新的等级
我很想看看其他人想出了什么解决方案。我很想看看他们是如何做到的!但是,是的,计划是定期生成它们。@而且,不管索引或硬件有多好,有时候运行查询的成本太高了,每小时或每天运行一次冗长的操作会大大超过这一成本。即使插入了限制,在我的大数据集中,这个查询似乎永远都不会完成。我想可能有什么东西坏了。