I am designing the database for online card game with MySQL and PHP.
I know that both of them are not the speed daemons recommended for online games, but they work fine for my project.
I am at the optimization phase (the game alpha is ready and tested for bugs and speed) and I've found that:
- When I use MySQL stored functions and foreign keys checks I have an extra security and readability.
- When I resign from them and use the database just as "flat" tables with records (without stored functions and foreign keys checks) I have an extra speed.
I made a simple test for it and here are the results:
I have a problem with the interpretation. Of course, the PHP direct calls are faster here, but does this difference really matters? Even if it's a lot as percentage difference, the real time (in s, ms) and "lags" for players is the only thing that matters.
The average request-respond time for the game server is around 50-200ms
and it results in a good user experience - smooth results, not noticeable in card game (note: it's card turn-based game, not a real time shooter!).
So, should I care about those differences?
If the time difference is not important I will prefer:
$mysqli->query("SELECT add_player('".$login."', '".$password."');
over:
$mysqli->query("INSERT INTO players (login, `password`, registered, last_logged, active_deck_id) VALUES ('".$login."', '".$password."', now(), now(), 0)");
$player_id = $mysqli->insert_id;
$mysqli->query("INSERT INTO decks (`name`, player_id) VALUES (`sample deck`, ".$player_id.")");
$mysqli->query("UPDATE players SET active_deck_id = ".$mysqli->insert_id." WHERE player_id = ".$player_id);
for the security and readability reasons. But the speed is very important for my game project and the resources I have are limited.
The code of the test (the execution time limit for php was disabled):
<?php
$maxSteps = 50;
/* speed test - mysql function with foreign key restrictions vs direct calls from php */
while($maxSteps <= 5000){
//-------------------------------------------------------------------------------
$login = "login";
$password = "password";
$mysqli = new mysqli("localhost", "root", "", "fantasy_forces2"); //the database without any stored functions or foreign key restrictions
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
//echo "<h1>Series of PHP direct calls to MySQL START...</h1>";
$start = microtime(true);
$i=0;
while($i<$maxSteps){
$login .= $i;
$mysqli->query("INSERT INTO players (login, `password`, registered, last_logged, active_deck_id) VALUES ('".$login."', '".$password."', now(), now(), 0)");
$player_id = $mysqli->insert_id;
$mysqli->query("INSERT INTO decks (`name`, player_id) VALUES (`sample deck`, ".$player_id.")");
$mysqli->query("UPDATE players SET active_deck_id = ".$mysqli->insert_id." WHERE player_id = ".$player_id);
$i++;
}
$timeElapsed = microtime(true) - $start;
echo "<p>Series of PHP calls ENDED after ".$timeElapsed." seconds.</p> for ".$maxSteps." steps.";
//-------------------------------------------------------------------------------
$login = "login";
$password = "password";
$mysqli = new mysqli("localhost", "root", "", "fantasy_forces");
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
//echo "<h1>MySQL procedure + foreign key restrictions START...</h1>";
$start = microtime(true);
$i=0;
while($i<$maxSteps){
$login .= $i;
if (!$mysqli->query("SELECT add_player('".$login."', '".$password."')")) {
echo "CALL failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
$i++;
}
$timeElapsed = microtime(true) - $start;
echo "<p>MySQL procedure ENDED after ".$timeElapsed." seconds.</p> for ".$maxSteps." steps.";
//-------------------------------------------------------------------------------
$maxSteps = $maxSteps * 10;
}
?>
-- edit:
Turning off the foreign keys checks does not impact on the speed (it gives 2-3% difference). I believe the main reason for a longer time of MySQL stored functions execution is that (according to this source):
Every single connection to the MySQL server maintains it’s own stored procedure cache. (...) If your application uses stored procedures, the connection is compiling the stored procedure, storing it in a cache, and destroying that cache every single time you connect to the database server and issue a CALL statement.
Moreover (the same source):
Every person that asks this question assumes something about MySQL’s stored procedure implementation; they incorrectly believe that stored procedures are compiled and stored in a global stored procedure cache, similar to the stored procedure cache in Microsoft SQL Server or Oracle. This is wrong. Flat-out incorrect.