Хранимые функции MySQL с проверкой внешних ключей по сравнению с простыми прямыми вызовами из переполнения стека

Я проектирую базу данных для карточной онлайн-игры с MySQL и PHP.

Я знаю, что оба они не рекомендуются для скорости онлайн-играми, но они отлично работают для моего проекта.

Я нахожусь на этапе оптимизации (игровая альфа готова и проверена на ошибки и скорость), и я обнаружил, что:

  • Когда я использую хранимые функции MySQL и проверки внешних ключей, у меня появляется дополнительная безопасность и удобство чтения.
  • Когда я ухожу из них и использую базу данных как «плоские» таблицы с записями (без сохраненных функций и проверок внешних ключей), у меня появляется дополнительная скорость.

Я сделал простой тест для этого, и вот результаты:
введите описание изображения здесь
введите описание изображения здесь

У меня проблема с интерпретацией. Конечно, прямые вызовы PHP здесь быстрее, но действительно ли это различие имеет значение? Даже если разница в процентах очень велика, единственное, что имеет значение, — это реальное время (в с, мс) и «лаги» для игроков.

Среднее время запроса-ответа для игрового сервера составляет около 50-200ms и это приводит к хорошему пользовательскому опыту — гладкие результаты, не заметные в карточной игре (примечание: это карточная пошаговая игра, а не шутер в реальном времени!).

Итак, я должен заботиться об этих различиях?

Если разница во времени не важна, я предпочитаю:

$mysqli->query("SELECT add_player('".$login."', '".$password."');

над:

$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);

по соображениям безопасности и читаемости. Но скорость очень важна для моего игрового проекта, и ресурсы у меня ограничены.

Код теста (ограничение по времени выполнения для php было отключено):

<?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;
}
?>

— редактировать:

Отключение проверок внешних ключей не влияет на скорость (это дает разницу в 2-3%). Я считаю, что основной причиной более длительного времени выполнения хранимых функций MySQL является то, что (согласно этот источник):

Каждое отдельное соединение с сервером MySQL поддерживает свой собственный
кеш процедур. (…) Если ваше приложение использует хранимые процедуры, соединение компилирует хранимую процедуру, сохраняет ее в кэше и уничтожает этот кэш каждый раз, когда вы подключаетесь к серверу базы данных и запускаете оператор CALL.

Более того (тот же источник):

Каждый, кто задает этот вопрос, предполагает что-то о реализации хранимых процедур MySQL; они ошибочно полагают, что хранимые процедуры компилируются и хранятся в глобальном кэше хранимых процедур, аналогично кешу хранимых процедур в Microsoft SQL Server или Oracle. Это не верно. Вычеркнуто неверно.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]