10000个学生,根据快速的根据考分来计算每个学生的击败率?
举个例子,10000个学生来考试,考完后提交得分,需要根据得分来计算学生的击败率(比如,我打败了90%的同学),每个学生提交答案的试卷不确定,有快,有慢。
我的疑问:每个学生提交答案后,所有学生的击败率都要重新计算,内存溢出了。
我现在的计算方式:按分数desc排序,循环每个学生,计算得分比这个学生多的人有多少。
我是一次取10000条记录呢,还是每次取100条数据,多循环几次?
10000个学生,根据快速的根据考分来计算每个学生的击败率?
举个例子,10000个学生来考试,考完后提交得分,需要根据得分来计算学生的击败率(比如,我打败了90%的同学),每个学生提交答案的试卷不确定,有快,有慢。
我的疑问:每个学生提交答案后,所有学生的击败率都要重新计算,内存溢出了。
我现在的计算方式:按分数desc排序,循环每个学生,计算得分比这个学生多的人有多少。
我是一次取10000条记录呢,还是每次取100条数据,多循环几次?
楼主这问题提的有点怪。击败率,无非就是分数比自己低的人,两条sql语句,一条交卷人数count,一条分数比自己低的人数count,两条sql语句不至于内存溢出吧!
像楼主那个样操作,每个人一提交,就更新之前所有提交的人的击败率,不内存溢出才有鬼。
如果楼主把这个击败率当成实时更新的字段。那只能用计划任务定时更新。
感觉没必要。一般来说数据列表都会分页,遍历的时候20条左右,就统计一次总人数,然后这20 count比他分数低的,花费不了多少时间。至于后期如果要数据导出,怕影响效率,写个脚本,直接把击败率一次性更新不就好了。
你应该不是实时的把,即便是实时的你也可以做个`loding`,等确定所有人交卷完成再请求服务端进行排名和击败率把
120
分钟我觉得楼主最主要等是没搞明白产品逻辑把 ,您的那个循环是搞什么...
没有必要实时计算所有人的击败率,
只需要在学生提交或者提交之后再次查询时计算这一个学生的击败率即可,
分数字段加个索引,每次计算一下分数比他低的人有多少,
提交的总人数做一个计数器就可以,每提交一个+1,计算击败率直接拿过来用就行了,效率很高,
最多就是10000个人同时请求而已,这是并发需求,服务器处理就可以了
数据表中只记录学生、分数
create table stu(
stuid int,
score FLOAT
)
另外建个视图
select stuid,(select count(1) from stu t2 where t2.score < t1.score)/(select count(*) from stu t3)*100 as beatRate
from stu t1
5 回答3.4k 阅读✓ 已解决
3 回答3.7k 阅读✓ 已解决
1 回答4.2k 阅读✓ 已解决
3 回答1.9k 阅读✓ 已解决
2 回答2.3k 阅读✓ 已解决
5 回答1.4k 阅读
2 回答2.1k 阅读
按你的描述,如果有以十亿个人,那你十亿个人都要重新算啊?这个时候肯定要换技术实现方式,使用 redis 的有序集合就可以轻松达到你的目标。简单说一下。
存储学生成绩到成绩表中:以学生唯一 id 为键,分数为值,将数据存储到 redis 有序集合中,假设成绩表
redis 键名为:
student_score_table
,插入语法:ZADD 成绩表键名 学生分数 学生id
,例如:ZADD student_score_table 66 1
;获取成绩表中学生总数$count:
ZCARD student_score_table
;获取当前学生的成绩排名$rank:
ZRANK student_score_table 学生id
;计算得到该学生的击败率$beat_rate(保留两位小数):
$beat_rate = round((1 - $rank / $count), 2) . '%';
;获取排名前十的学生:
ZRANGE student_score_table 1 10
;获取成绩在80到100之间即优秀学生:
ZRANGE student_score_table 80 90 WITHSCORES
;参考
Redis 有序集合(sorted set)