From 4aa09a294eb7d92bd4dbdff3d80681579d51c3c1 Mon Sep 17 00:00:00 2001 From: hided62 Date: Thu, 30 Jul 2026 17:12:22 +0000 Subject: [PATCH] perf: reduce MariaDB turn queue round trips --- hwe/func_command.php | 102 +++++++++++++++++++++++++++--------------- hwe/sammo/General.php | 79 +++++++++++++++++++++++++------- 2 files changed, 128 insertions(+), 53 deletions(-) diff --git a/hwe/func_command.php b/hwe/func_command.php index 8dbc22c9..a3524184 100644 --- a/hwe/func_command.php +++ b/hwe/func_command.php @@ -42,15 +42,21 @@ function pushGeneralCommand(int $generalID, int $turnCnt=1){ $db = DB::db(); - $db->update('general_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt) - ], 'general_id=%i ORDER BY turn_idx DESC', $generalID); - $db->update('general_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxTurn), - 'action'=>'휴식', - 'arg'=>'{}', - 'brief'=>'휴식' - ], 'general_id=%i AND turn_idx >= %i', $generalID, GameConst::$maxTurn); + $db->query( + 'UPDATE general_turn AS dst + LEFT JOIN general_turn AS src + ON src.general_id = dst.general_id + AND src.turn_idx = dst.turn_idx - %i + SET dst.action = IF(src.id IS NULL, %s, src.action), + dst.arg = IF(src.id IS NULL, %s, src.arg), + dst.brief = IF(src.id IS NULL, %s, src.brief) + WHERE dst.general_id = %i', + $turnCnt, + '휴식', + '{}', + '휴식', + $generalID + ); } function pullGeneralCommand(int $generalID, int $turnCnt=1){ @@ -67,15 +73,21 @@ function pullGeneralCommand(int $generalID, int $turnCnt=1){ $db = DB::db(); - $db->update('general_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxTurn), - 'action'=>'휴식', - 'arg'=>'{}', - 'brief'=>'휴식' - ], 'general_id=%i AND turn_idx < %i', $generalID, $turnCnt); - $db->update('general_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt) - ], 'general_id=%i ORDER BY turn_idx ASC', $generalID); + $db->query( + 'UPDATE general_turn AS dst + LEFT JOIN general_turn AS src + ON src.general_id = dst.general_id + AND src.turn_idx = dst.turn_idx + %i + SET dst.action = IF(src.id IS NULL, %s, src.action), + dst.arg = IF(src.id IS NULL, %s, src.arg), + dst.brief = IF(src.id IS NULL, %s, src.brief) + WHERE dst.general_id = %i', + $turnCnt, + '휴식', + '{}', + '휴식', + $generalID + ); } function repeatGeneralCommand(int $generalId, int $turnCnt){ @@ -126,15 +138,23 @@ function pushNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ $db = DB::db(); - $db->update('nation_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx + %i', $turnCnt) - ], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx DESC', $nationID, $officerLevel); - $db->update('nation_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx - %i', GameConst::$maxChiefTurn), - 'action'=>'휴식', - 'arg'=>'{}', - 'brief'=>'휴식' - ], 'nation_id=%i AND officer_level=%i AND turn_idx >= %i ORDER BY turn_idx ASC', $nationID, $officerLevel, GameConst::$maxChiefTurn); + $db->query( + 'UPDATE nation_turn AS dst + LEFT JOIN nation_turn AS src + ON src.nation_id = dst.nation_id + AND src.officer_level = dst.officer_level + AND src.turn_idx = dst.turn_idx - %i + SET dst.action = IF(src.id IS NULL, %s, src.action), + dst.arg = IF(src.id IS NULL, %s, src.arg), + dst.brief = IF(src.id IS NULL, %s, src.brief) + WHERE dst.nation_id = %i AND dst.officer_level = %i', + $turnCnt, + '휴식', + '{}', + '휴식', + $nationID, + $officerLevel + ); } function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ @@ -157,15 +177,23 @@ function pullNationCommand(int $nationID, int $officerLevel, int $turnCnt=1){ $db = DB::db(); - $db->update('nation_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx + %i', GameConst::$maxChiefTurn), - 'action'=>'휴식', - 'arg'=>'{}', - 'brief'=>'휴식', - ], 'nation_id=%i AND officer_level=%i AND turn_idx < %i', $nationID, $officerLevel, $turnCnt); - $db->update('nation_turn', [ - 'turn_idx'=>$db->sqleval('turn_idx - %i', $turnCnt) - ], 'nation_id=%i AND officer_level=%i ORDER BY turn_idx ASC', $nationID, $officerLevel); + $db->query( + 'UPDATE nation_turn AS dst + LEFT JOIN nation_turn AS src + ON src.nation_id = dst.nation_id + AND src.officer_level = dst.officer_level + AND src.turn_idx = dst.turn_idx + %i + SET dst.action = IF(src.id IS NULL, %s, src.action), + dst.arg = IF(src.id IS NULL, %s, src.arg), + dst.brief = IF(src.id IS NULL, %s, src.brief) + WHERE dst.nation_id = %i AND dst.officer_level = %i', + $turnCnt, + '휴식', + '{}', + '휴식', + $nationID, + $officerLevel + ); } function repeatNationCommand(int $nationID, int $officerLevel, int $turnCnt){ @@ -494,4 +522,4 @@ function setNationCommand(int $generalID, array $turnList, string $command, ?arr 'arg_test'=>true, 'reason'=>'success' ]; -} \ No newline at end of file +} diff --git a/hwe/sammo/General.php b/hwe/sammo/General.php index 68066a78..43a35816 100644 --- a/hwe/sammo/General.php +++ b/hwe/sammo/General.php @@ -1045,18 +1045,64 @@ class General extends GeneralBase implements iAction /** @var Map|null */ $rawAccessLog = null; + $rankColumnValues = array_map(fn (\BackedEnum $e) => $e->value, $rankColumn); if (!$accessLogColumn) { - $rawGeneral = $db->queryFirstRow('SELECT %l FROM general WHERE no = %i', Util::formatListOfBackticks($column), $generalID); + if ($rankColumn) { + $rawGeneral = $db->queryFirstRow( + 'SELECT %l, ( + SELECT GROUP_CONCAT( + CONCAT(`type`, CHAR(61), `value`) + ORDER BY `type` + ) + FROM rank_data + WHERE rank_data.general_id = general.no + AND `type` IN %ls + ) AS `_rank_values` + FROM general WHERE no = %i', + Util::formatListOfBackticks($column), + $rankColumnValues, + $generalID + ); + } else { + $rawGeneral = $db->queryFirstRow( + 'SELECT %l FROM general WHERE no = %i', + Util::formatListOfBackticks($column), + $generalID + ); + } } else { - $rawGeneral = $db->queryFirstRow( - 'SELECT %l, %l FROM `general` LEFT JOIN general_access_log - ON general.no = general_access_log.general_id WHERE no = %i', - Util::formatListOfBackticks($column), - Util::formatListOfBackticks($accessLogColumn), - $generalID - ); + if ($rankColumn) { + $rawGeneral = $db->queryFirstRow( + 'SELECT %l, %l, ( + SELECT GROUP_CONCAT( + CONCAT(`type`, CHAR(61), `value`) + ORDER BY `type` + ) + FROM rank_data + WHERE rank_data.general_id = general.no + AND `type` IN %ls + ) AS `_rank_values` + FROM `general` LEFT JOIN general_access_log + ON general.no = general_access_log.general_id + WHERE no = %i', + Util::formatListOfBackticks($column), + Util::formatListOfBackticks($accessLogColumn), + $rankColumnValues, + $generalID + ); + } else { + $rawGeneral = $db->queryFirstRow( + 'SELECT %l, %l FROM `general` LEFT JOIN general_access_log + ON general.no = general_access_log.general_id WHERE no = %i', + Util::formatListOfBackticks($column), + Util::formatListOfBackticks($accessLogColumn), + $generalID + ); + } + } + if ($accessLogColumn) { $rawAccessLog = new Map(); foreach ($accessLogColumn as $accessLogKey) { if (!key_exists($accessLogKey->value, $rawGeneral)) { @@ -1076,15 +1122,16 @@ class General extends GeneralBase implements iAction $rawRankValues = new Map(); if ($rankColumn) { - $rawValue = $db->queryAllLists( - 'SELECT `type`, `value` FROM rank_data WHERE general_id = %i AND `type` IN %ls', - $generalID, - array_map(fn (\BackedEnum $e) => $e->value, $rankColumn) - ); - foreach ($rawValue as [$rawRankType, $rankValue]) { - $rankType = RankColumn::tryFrom($rawRankType); - $rawRankValues->put($rankType, $rankValue); + $rawRankPairs = $rawGeneral['_rank_values']; + foreach ($rawRankPairs === null || $rawRankPairs === '' + ? [] + : explode(',', $rawRankPairs) as $rawRankPair + ) { + [$rawRankType, $rankValue] = explode('=', $rawRankPair, 2); + $rankType = RankColumn::from($rawRankType); + $rawRankValues->put($rankType, (int) $rankValue); } + unset($rawGeneral['_rank_values']); }