From 5a967055f492fb04918e6efc827c400464dc6bb3 Mon Sep 17 00:00:00 2001 From: Martin Ambrus Date: Fri, 27 Oct 2017 21:04:16 +0200 Subject: [PATCH] refactor: using indexed temporary table as array works speed wonders :) --- GameEngine/Database.php | 6 +- var/db/datagen-oasis-troops-regen.sql | 212 ++++++-------------------- var/db/datagen-world-data.sql | 3 + 3 files changed, 53 insertions(+), 168 deletions(-) diff --git a/GameEngine/Database.php b/GameEngine/Database.php index 9ede26f3..07668b68 100755 --- a/GameEngine/Database.php +++ b/GameEngine/Database.php @@ -908,13 +908,13 @@ class MYSQLi_DB implements IDbConnection { global $autoprefix; if (is_array($wid)) { - $wid = '"'.implode(',', $wid).'"'; + $wid = '(' . implode('),(', $wid) . ')'; } else { - $wid = (int) $wid; + $wid = '(' . (int) $wid . ')'; } // load the oasis regeneration (in-game) and units generation (during install) SQL file - // and replace village ID for the given $wid + // and replace village IDs for the given $wid $str = file_get_contents($autoprefix."var/db/datagen-oasis-troops-regen.sql"); $str = preg_replace(["'%PREFIX%'", "'%VILLAGEID%'", "'%NATURE_REG_TIME%'"], [TB_PREFIX, $wid, ($automation ? NATURE_REGTIME : -1)], $str); $result = $this->dblink->multi_query($str); diff --git a/var/db/datagen-oasis-troops-regen.sql b/var/db/datagen-oasis-troops-regen.sql index 84b980db..c88a18f3 100644 --- a/var/db/datagen-oasis-troops-regen.sql +++ b/var/db/datagen-oasis-troops-regen.sql @@ -16,15 +16,29 @@ SET @natureRegTime = %NATURE_REG_TIME%; --- Oasis village ID. --- --- type: int --- description: when > -1, used to regenerate units of a single oasis (when conquered > unoccupied) --- when == -1, installation or server reset in progress, all oasis data are updated +-- A temporary table with oasis village ID(s). +-- Used instead of variable so we can work with it as with array. +-- The only other option would be to repeat IDs replacements below +-- or define them once in a string and use FIND_IN_SET() for lookups, +-- which is TERRIBLE, performance-wise (since it doesn't use indexes). -SET @village = %VILLAGEID%; +CREATE TEMPORARY TABLE %PREFIX%oids (id INT NOT NULL, PRIMARY KEY (id)); +INSERT INTO %PREFIX%oids VALUES %VILLAGEID%; + +-- Equivalent to "VILLAGEID === -1" (in PHP). Determines whether we have +-- any single oasis to actually update (mode = conquered > unocupied) +-- or we're updating 1 or more specific oasis (mode = install, server reset, Automation's nature regen). + +SET @noVillage = ((SELECT id FROM %PREFIX%oids LIMIT 1) = -1); + + + + +-- faster access to first oasis ID, so we don't need to reselect all the time below +SET @firstVillage = (SELECT id FROM %PREFIX%oids LIMIT 1); + -- minimum and maximum number of units for oasis with "high" field set to 0 SET @minUnitsForOasis0 = 15; SET @maxUnitsForOasis0 = 30; @@ -59,19 +73,7 @@ UPDATE %PREFIX%odata WHERE @natureRegTime = -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(conqured, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - conqured = @village - ) - ); + conqured = @firstVillage; -- --------------------------------------------- -- remove past reports (conquered > unoccupied) @@ -80,19 +82,7 @@ DELETE FROM %PREFIX%ndata WHERE @natureRegTime = -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(toWref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - toWref = @village - ) - ); + toWref = @firstVillage; -- ---------------------------------------------------------------- @@ -105,19 +95,7 @@ SET WHERE @natureRegTime > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(wref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - wref = @village - ) - ); + wref IN ( SELECT id FROM %PREFIX%oids ); -- ----------------------------------------------------------------------- @@ -137,7 +115,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 AND vref IN( SELECT @@ -150,21 +128,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND @@ -205,7 +171,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -218,21 +184,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND @@ -271,7 +225,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -284,21 +238,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND u31 <= ( @@ -335,7 +277,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -348,21 +290,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND u31 <= ( @@ -398,7 +328,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -411,21 +341,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND u31 <= ( @@ -462,7 +380,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -475,21 +393,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND u31 <= ( @@ -527,7 +433,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -540,21 +446,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND u31 <= ( @@ -600,7 +494,7 @@ UPDATE %PREFIX%units u WHERE ( ( - @village = -1 + @firstVillage = -1 = -1 AND vref IN( SELECT @@ -613,21 +507,9 @@ UPDATE %PREFIX%units u ) OR ( - @village > -1 + @firstVillage = -1 > -1 AND - ( - ( - -- should we have a list of IDs, we need to use FIND_IN_SET - LOCATE(",", @village) > 0 - AND - FIND_IN_SET(vref, @village) - ) - OR - ( - -- for a single ID, we use a simple condition which can definitely use an index as well - vref = @village - ) - ) + vref IN ( SELECT id FROM %PREFIX%oids ) ) ) AND u31 <= ( diff --git a/var/db/datagen-world-data.sql b/var/db/datagen-world-data.sql index 1187f2ce..6c067c62 100644 --- a/var/db/datagen-world-data.sql +++ b/var/db/datagen-world-data.sql @@ -96,6 +96,8 @@ INSERT INTO %PREFIX%wdata WHERE @row2 <= (%WORLDSIZE% - 1)) as y ) as generator; + + -- populate oasis data INSERT INTO %PREFIX%odata SELECT @@ -138,6 +140,7 @@ INSERT INTO %PREFIX%odata oasistype <> 0; + -- create some defensive units for existing oasis INSERT INTO %PREFIX%units (vref) SELECT