2011-11-26 45 views
0

我有一个相当大的游戏,30-40-50人在一天中的大多数点。我们将有关坦克的信息存储到mysql数据库中,当他们拍摄或失去健康时,我们将其转储到数据库。由于这个原因,我们看到一个非常高的处理器和HDD Spike,结果是游戏滞后。Mysql高UPDATE SELECT导致滞后

犯规声明:

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

['EXPLAIN'](http://dev.mysql.com/doc/refman/5.1/en/explain.html)的输出结果是什么? – outis

回答

2

有些事情你可以做,但你已经达到了通过的硬阈值之一。你有一个写入重型系统的地方,它只是写得不够快。

有性能

  1. 计算神值innodb_log_file_size
  2. 设置innodb_flush_log_at_trx_commit为0或2。注意,1(默认值)改善的某些方面是唯一符合ACID值,但将其更改为0或2提供了更好的性能。

当然还有更多的方法,但这两个很重要。

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`), 

并不需要在所有的主键(的第1部分)可以代替KEY MapID (MapID)

KEY idx_mapdata可如果你正在寻找扩大了很多比你现在在哪里,那么你显然需要寻找到软件的变化,这将有利于更多降至(MapID, Color)

1

,但如果你” d在开发时几乎不花费任何代价就可以提高性能,那么如果您还没有使用固态驱动器,则可以考虑切换到固态驱动器。

您是否考虑过读取/写入RAM存储器而不是活动播放器的数据库,然后在数据库不再活动时将其保存到数据库中?这需要一些开发时间,但肯定会解决您的问题。

+0

我们实际上有一个内存缓存系统,但都有其负面和积极的。我总是可以恢复到那个系统,但是我希望mysql能够处理它。我已经做了一些调整,似乎运行顺利! – willthiswork89

+0

其实,如果你有一个有很多玩家的实时游戏服务器,我想添加一些类似的最吸引人的场景。在数据库中存储每一个(游戏状态的变化)没有什么意义,除非你在系统崩溃的情况下必须100%安全。在极端情况下,甚至可以将你的(游戏)应用程序服务器存储在数据库中,仅在游戏的开始和结束时(以及“暂停”状态,如果这是一个选项,以便游戏可以在以后继续)。 –