【问题标题】:Any ideas on how to speed up this query?有关如何加快此查询的任何想法?
【发布时间】:2015-03-24 01:28:11
【问题描述】:

我有一个使用 mysql 运行的排行榜,我的所有游戏都连接到它。与此类似的查询每天被调用数百万次。唯一改变的是用户得分和 appID 取决于游戏。此查询从他们正在玩的应用程序中提取用户排名。我已经有了分数和 appID 的索引。

SELECT count(*) FROM users_scores WHERE score > 13956 AND appID='60'

这是一个相当基本的查询,所以我不确定查询本身是否可以做很多事情。该表本身有大约 220 万条记录,并且每天都在增长。我想知道是否可以在表中添加一个名为 rank 的列,然后每隔 5 分钟左右让 cron 更新所有排名。更新所有等级时,服务器会承受沉重的负载,但是每秒运行该查询 90 次以上会更好吗?

或者您是否有其他我没有想到的想法?

编辑这里是表格设置

CREATE TABLE IF NOT EXISTS `users_scores` (
  `deviceID` varchar(36) NOT NULL,
  `appID` int(3) NOT NULL,
  `score` bigint(20) NOT NULL,
  `username` varchar(20) NOT NULL,
  `avatar` int(3) NOT NULL,
  `userData` text NOT NULL,
  PRIMARY KEY (`deviceID`,`appID`),
  KEY `user_score` (`appID`,`score`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;;

这是上面查询的解释

【问题讨论】:

  • 您需要向我们展示表和索引定义,以及每个表的行数。也许您的表格定义不佳。也许索引没有正确创建。也许您认为您在该列上没有索引。没有看到表和索引定义,我们无法判断。我们需要行计数,因为这会影响查询计划。如果您知道如何进行EXPLAIN 或获得执行计划,请将结果也放入问题中。
  • 记分卡更新了多少次?如果更新频率小于显示排行榜的频率,您可能会考虑存储与用户对应的排名,并在每次分数变化时更新排名
  • @AndyLester 好的我上传了表结构并解释了查询
  • @vishva 分数表一直在更新。每当用户查看排行榜时,他们都会提交他们的分数并更新表格。话虽如此,我有一个 cron 运行,它将前 30 个分数缓存到一个 json 文件中,当用户加载排行榜时,他们将看到缓存的 json 文件而不是表的实时查询。我认为每次他们的排名变化时更新排名对数据库来说太重了。

标签: mysql performance query-optimization leaderboard


【解决方案1】:

在 (appID, score) 上的表上有一个复合索引

这样,where 子句将直接跳转到您的 AppID 60,然后跳转到分数 13956,并且只获得更高的分数。由于您正在执行计数(*),因此无需返回原始数据页面即可获得资格。

【讨论】:

  • 是的,直到我发布了表格结构,我才意识到这一点。最好的做法是什么,删除索引并使用主键?
  • @Dave,主键,我会根据唯一 ID 原样离开。我只会将 SECOND 索引创建为两列,但将 AppID 保持在第一个位置,得分在第二个。
  • 好的,我在第一篇文章中编辑了表格,现在看起来怎么样?
  • @Dave,看起来不错...在这种情况下,它既是复合索引又是覆盖索引,以防您想查看这些术语:)
  • device_id 是 UUID?如果是这样,PRIMARY KEY 糟透了。我是 。 UUID 是非常随机的。这会伤害 INSERT 和 SELECT。当表变得比缓冲区池中的缓存更大时,这是一场灾难。
猜你喜欢
  • 1970-01-01
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-26
相关资源
最近更新 更多