我正在使用以下查询来创建本周排名前10位的排行榜。
SELECT
users.id,
concat(users.first_name, ' ', users.last_name) as name,
users.picture_url,
MAX(rounds.speed) as speed,
AVG(rounds.accuracy) as accuracy,
SUM(rounds.score) as score,
users.level
FROM users INNER JOIN rounds ON users.email=rounds.email
WHERE DATE(rounds.dateTime) BETWEEN CURDATE()-INTERVAL 1 WEEK AND CURDATE()
GROUP BY users.id
ORDER BY score DESC, speed DESC
LIMIT 10
目前,运行此查询需要 6秒。表'rounds'包含大约3000行。很快它会变得更大。因此,一旦用户打开排行榜,加载时间超过6秒!
有没有办法缓存或改进查询以便加载更快?
数据库:MySQL 后端:PHP5 框架:Codeigniter
答案 0 :(得分:1)
您可以采取许多措施来解决此问题 - 由于MAX
和AVG
元素涉及表格中所有行之间的比较分析,因此查询速度很慢。
您可以采取一些措施来加快速度。
将其分解为多个查询。您根据ORDER BY score DESC, speed DESC
抓取了前10位用户,因此您无需在同一查询中获取AVG(rounds.accuracy)
。获取前10位用户中的user_id
,然后分别查询这10位用户的AVG(rounds.accuracy)
数据库。
根据排行榜的性质添加一些逻辑。每次更新排行榜时都不太可能需要检查所有行。在排行榜上排名第100的人今天可能不太可能进入前10名,如果是这样的话,你今天不需要检查那个人的得分。
如果您添加WHERE user_id IN
语句,它将显着加快查询速度,并且仅包含可能位于前10名的最高用户数。可能在任何特定日期只有30,40或者50个可能位于前10名的用户。如果是这种情况,那么您可以创建一个包含前50个用户ID的单独表格,每天运行一次“慢”查询以获得前50名。在您的排行榜查询中添加WHERE user_id IN (select id from top_users)
条件。
可能有其他方法和方法可以提高您的查询速度。这些是一些有用的东西。很多这取决于你的应用程序/排行榜,以及你在使用它时所了解的内容。
答案 1 :(得分:1)
添加@Dan答案。 使用Explain来检查查询为什么花时间,检查索引是否正确构建,并且只需要上周的数据,你可以在datetime上创建索引,这将非常有用。当你使用数学函数和order by时,Mysql需要排序并计算增加查询时间的值。 您还可以启用mysql缓存并增加缓存大小 检查此Here .