MySQL通过建表优化、索引加速和聚合查询即可高效支撑排行榜,关键在于预存分数字段、为score建降序索引、用ORDER BY+LIMIT查Top N,并结合Redis缓存提升响应速度。

排行榜功能核心在于高效排序与实时统计,MySQL 通过合理建表、索引优化和聚合查询即可支撑常见场景(如日榜、周榜、总榜),无需复杂中间件。
设计支持排行榜的用户数据表
关键字段需覆盖排序依据(如积分、得分、播放量)和时间维度(用于分时段榜单)。示例结构:
- user_id:主键,唯一标识用户
- score:当前累计得分(用于总榜)
- score_today:当日新增得分(用于日榜,每日零点重置或用定时任务归零)
- score_week:本周新增得分(同理可维护,或用时间范围动态计算)
- updated_at:最后更新时间,便于排查和增量同步
避免在查询时临时计算(如 SUM(score) OVER(PARTITION BY DATE(create_time))),高频榜单优先预存结果字段,提升响应速度。
用 ORDER BY + LIMIT 快速获取 Top N
最常用且高效的方式。例如查总榜前100名:
SELECT user_id, score FROM users ORDER BY score DESC LIMIT 100;
注意两点:
- 必须为 score 字段建立降序索引:
CREATE INDEX idx_score_desc ON users(score DESC);(MySQL 8.0+ 支持显式 DESC 索引,5.7 及以前默认升序,但对 ORDER BY score DESC 仍可利用 B+ 树反向扫描) - 若存在并列排名(如相同分数需同名次),需额外处理“跳位”逻辑(如 1,1,3,4),纯 SQL 需借助变量或窗口函数;MySQL 8.0+ 推荐用
RANK() OVER(ORDER BY score DESC)
按时间范围动态统计(日榜/周榜)
当不预存 daily/weekly 字段时,可用带 WHERE 的聚合查询。例如查昨日得分 Top 50:
SELECT user_id, SUM(score_delta) AS daily_score
FROM user_score_log
WHERE DATE(create_time) = CURDATE() - INTERVAL 1 DAY
GROUP BY user_id
ORDER BY daily_score DESC
LIMIT 50;
确保 create_time 有索引,并考虑组合索引提升效率:INDEX idx_user_time (user_id, create_time) 或 INDEX idx_time_score (create_time, score_delta),具体依查询模式而定。
缓存与更新策略平衡性能与实时性
排行榜不是强实时场景,建议加一层缓存:
- 每5–10分钟用定时任务刷新一次 Redis 有序集合(ZSET),键如
rank:weekly,成员为 user_id,分值为 score_week - 前端直接查 Redis,毫秒级响应;MySQL 仅承担写入和兜底校验
- 用户得分变更时,异步更新缓存(如用消息队列延迟双删),避免写库同时刷缓存导致不一致
冷启动或缓存失效时,回退到 MySQL 查询并重建缓存,保障可用性。










