我有一个相当大的游戏,白天最多点30-40-50人。我们将关于他们的坦克的信息存储到一个mysql数据库中,当他们射击或失去健康时,我们将其转储到数据库。由于这个原因,我们看到了非常高的处理器和HDD Spike,结果是在游戏中滞后。
违规言论:
UPDATE MapData
SET Health = @1, X = @2, Y = @3,TotalPoints = @4
, RankPoints = @5
WHERE MapID = @6
AND TankID = @7
AND Color = @8
我想知道是否有一些我可以做的事情来帮助解决滞后问题。
CREATE TABLE `mapdata` (
`MapID` int(11) NOT NULL,
`TankID` int(11) NOT NULL,
`Color` tinyint(4) NOT NULL,
`X` int(11) DEFAULT ''-1'',
`Y` int(11) DEFAULT ''-1'',
`Rank` tinyint(4) NOT NULL DEFAULT ''0'',
`Health` int(11) NOT NULL DEFAULT ''1000'',
`Armors` tinyint(4) NOT NULL DEFAULT ''0'',
`Duals` tinyint(4) NOT NULL DEFAULT ''0'',
`Missiles` tinyint(4) NOT NULL DEFAULT ''0'',
`Homings` tinyint(4) NOT NULL DEFAULT ''0'',
`Radars` tinyint(4) NOT NULL DEFAULT ''0'',
`Beacons` tinyint(4) NOT NULL DEFAULT ''0'',
`HasRankKill` bit(1) NOT NULL DEFAULT b''0'',
`TotalPP` bigint(20) NOT NULL DEFAULT ''0'',
`RankPP` bigint(20) NOT NULL DEFAULT ''0'',
`KillCount` int(11) NOT NULL DEFAULT ''0'',
`DeathCount` int(11) NOT NULL DEFAULT ''0'',
`TimePlayed` time NOT NULL DEFAULT ''00:00:00'',
`EnabledEquipment` tinyint(4) NOT NULL DEFAULT ''0'',
`Prestige` tinyint(4) NOT NULL DEFAULT ''0'',
PRIMARY KEY (`MapID`,`TankID`,`Color`),
KEY `MapID` (`MapID`),
KEY `TankID` (`TankID`),
KEY `idx_mapdata` (`MapID`,`Color`,`TankID`),
CONSTRAINT `mapdata_ibfk_1` FOREIGN KEY (`MapID`) REFERENCES `maps` (`ID`) ON DELETE CASCADE,
CONSTRAINT `mapdata_ibfk_2` FOREIGN KEY (`TankID`) REFERENCES `tank` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
有没有我可以将表持久保存在内存中而不是hdd中,并将它经常转储回磁盘?
答案 0 :(得分:2)
有些事情你可以做,但你已经达到了一个难以通过的门槛。你有一个写重系统而且编写速度不够快的那个。
有一些提高性能的方法
当然还有更多方法,但这两个方面很重要。
答案 1 :(得分:2)
要检查的一件事是您的配置是否针对InnoDB进行了优化。默认的MySQL设置通常(取决于确切的版本,但仍然)未针对InnoDB进行优化,但更适合MyISAM引擎。
Percona的网站有一个很好的介绍: Innodb Performance Optimization Basics
该名单上的第5号(设置innodb_flush_log_at_trx_commit=2
)正是安德烈亚斯提出的。还有更多选择需要检查。
关于您的问题,您可以使用 Memory engine 。当您的应用程序启动时,它会将表从磁盘复制到相同的内存表,然后将其用于所有操作,从而逐步更新磁盘表。或者它只能加载每次所需的数据(在游戏玩家的数据中激活)
或者,您可以在应用程序中添加一些(延迟)机制,该机制不会将每个更新作为单独的事务发送,而是分批发送。
您可以考虑的另一件事是对表进行垂直分区。如果您有一些很少更新的列和一些经常更新的列,您可以将表拆分为两部分。然后,更新将在宽度较小的表中完成。
你有4个索引但有些是多余的:
PRIMARY KEY (`MapID`,`TankID`,`Color`),
KEY `MapID` (`MapID`),
KEY `TankID` (`TankID`),
KEY `idx_mapdata` (`MapID`,`Color`,`TankID`),
根本不需要KEY MapID (MapID)
,因为可以使用主键的第一部分。
KEY idx_mapdata
可以缩减为(MapID, Color)
答案 2 :(得分:1)
如果您希望扩展比现在更多,那么您显然需要研究可以促进这一点的软件更改,但是如果您希望快速提升性能,几乎不需要开发费用如果您还没有使用固态驱动器,那么您可以考虑切换到固态驱动器。
您是否考虑过读取/写入ram内存而不是活动播放器的数据库,然后只是在内存不再有效时将内存持久保存到数据库中?这需要一些开发时间,但肯定会解决你的问题。