2011-11-26 63 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%安全。在極端情況下,甚至可以將你的(遊戲)應用程序服務器存儲在數據庫中,僅在遊戲的開始和結束時(以及「暫停」狀態,如果這是一個選項,以便遊戲可以在以後繼續)。 –