Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在MySQL和PHP中从500万行的记分牌中获得排名?_Php_Mysql_Database_Ranking - Fatal编程技术网

如何在MySQL和PHP中从500万行的记分牌中获得排名?

如何在MySQL和PHP中从500万行的记分牌中获得排名?,php,mysql,database,ranking,Php,Mysql,Database,Ranking,我有一个排行榜,其中有一个“得分”栏。我还在分数列上有一个索引,它允许我非常快速地按分数排序表格,甚至可以将前十名或任意数量的分数分割出来——即使有500万行 然而,我真正想要的是在排行榜上显示玩家的“排名”。我尝试过几种方法,但在处理超过100000行的数据时,似乎没有一种方法是有效的(它们开始占用超过半秒的时间,考虑到我预期当前有数百个用户,这太长了) 我目前正在使用以下查询来确定一个用户的排名,然后在我的输出中为高于这个排名的用户simlpy递增-但是速度非常慢 SELECT tro.s

我有一个排行榜,其中有一个“得分”栏。我还在分数列上有一个索引,它允许我非常快速地按分数排序表格,甚至可以将前十名或任意数量的分数分割出来——即使有500万行

然而,我真正想要的是在排行榜上显示玩家的“排名”。我尝试过几种方法,但在处理超过100000行的数据时,似乎没有一种方法是有效的(它们开始占用超过半秒的时间,考虑到我预期当前有数百个用户,这太长了)

我目前正在使用以下查询来确定一个用户的排名,然后在我的输出中为高于这个排名的用户simlpy递增-但是速度非常慢

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(使用旧分数和新分数),它将返回新的等级


我很想看看其他人想出了什么解决方案。

我很想看看他们是如何做到的!但是,是的,计划是定期生成它们。@而且,不管索引或硬件有多好,有时候运行查询的成本太高了,每小时或每天运行一次冗长的操作会大大超过这一成本。即使插入了限制,在我的大数据集中,这个查询似乎永远都不会完成。我想可能有什么东西坏了。