我需要在mysql innodb表中存储游戏用户配置文件。但是其中可能有数百万个,配置文件记录包含200多个int32值和其他几个用于游戏内数据的值。我需要评估每个200多个整数的用户排名。 我打算这样做(例如121级):
select count(distinct(val121)) from ldbrd where
val121<$current_usr_val order by val121 desc
或使用帮助表{id,maxscore,minscore,count}来提高速度。
我在这里看到两个问题:
表有200多个int字段。好吗?这样的表会快吗?
sql有64个索引的限制,所以我不能只为每个int字段创建一个索引,但没有索引这样的搜索会很慢。
但我很确定这项任务很常见。我的意思是有许多游戏有数百个级别 - 我认为糖果粉碎最为人所知。那人们如何解决呢?谢谢!
---更新
我决定在一个表中编写二进制字段中的配置文件(一个字段中的所有这些内容),并创建另一个用于评估排名的表:{id,user_id,level_no,score,timestamp}。但如果我们有100000个用户和200个级别,我们在此表中获得20M行。 是的,所有字段都有索引,但对于具有2个内核2.4Ghz和2 Gb RAM的VDS来说太过分了。例如,查询:
SELECT COUNT(*) FROM leaderboard WHERE level_no = 153
AND score < 10000 ORDER BY score DESC
在19秒内完成!它太多了,而且每秒会有很多请求,每个都需要进行等级评估。
此外,我还想过为每个级别存储一个表,也许这样会更快(至少它们会小得多)。
另一个想法 - 生成说每个级别每小时前100名。它非常简单快速:
SELECT score FROM leaderboard WHERE
level_no = 156 ORDER BY score DESC LIMIT 100
但每个人都想知道他的排名。我们可以添加'rank'字段但是在20M行表中的排名评估将花费很长时间,在此查询期间服务器将忙于其他人,我想避免它。 人们通常如何做这样的事情?
-----更新2
表架构:
CREATE TABLE IF NOT EXISTS `leaderboard` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`store_user_id` char(64) NOT NULL,
`level_no` int(11) NOT NULL,
`score` int(11) NOT NULL,
`timestamp` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `store_user_id` (`store_user_id`),
KEY `level_no` (`level_no`),
KEY `score` (`score`),
KEY `timestamp` (`timestamp`),
KEY `lev_sc` (`level_no`,`score`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY HASH (id)
PARTITIONS 10 */ AUTO_INCREMENT=19999831 ;
我最终对表格进行了分区并添加了(level_no,score)键。是19秒,现在:0,017秒。非常酷!
仍有疑问:
我应该在生产中分区表吗?我听说人们在分区时遇到了问题。
什么是最好的选择 - 拥有500个桌子 - 每个级别一个,或者一个比我现在大500倍的桌子?每个级别的表工作速度稍快一点(0,048秒对0,072秒),但只要我有几个表就可以了。 500多个表会以相同的速度工作吗?