Vallheru: Optymalizacja listy graczy online

Piotr Kowalczyk
05.09.2015

Mianowicie zwiększenie wydajności wczytywania listy graczy online, bo będziemy ją przechowywać w specjalnym typie tabeli bazodanowej trzymanej w RAMie który jest DUUUUUUŻO szybszy w zapisie/odczycie danych aniżeli HDD.

Z tego poradnika szczególnie to powinni skorzystać ci co maja dużo graczy online i dość sporo informacji jest pokazywana przez listę (serwerek BD się ucieszy ;D )

UWAGA: Poradnik jest POKAZOWY - każdy pokazany fragment kodu trzeba na własną rękę przerobić! Operacje na bazie danych wykonywane w PMA!

Pierwsze co zrobić trzeba to nową tabelkę w bazie z takich pól jakie ma zapytanie do BD od listy graczy. Załóżmy że jest ono takie:
 

$objQuery = $db -> Execute("SELECT id, user, rank FROM players WHERE lpv>=".$span." ORDER BY id ASC");

Pola z jakich korzysta to id, rank, user ORAZ lpv (klauzula WHERE) toteż tworzymy tabelkę o nazwie załóżmy playerlist z takich samych pól:

id (INT), dajemy je jako PRIMARY KEY (klucz podstawowy),

ale NIE DAJEMY NA NIE auto_increment !!!


user (VARCHAR) [30]
rank (VARCHAR) [40]
lpv (INT), dajemy na nie INDEX!
lip (INT), po co to pole - wyjaśnię potem.


Mechanizm składowania: MEMORY (wybrać HEAP jak nie ma MEMORY)



Teraz przechodzimy do plików PHP:

otwieramy head.php i wyszukujemy w okolicach 300-tnej linijki:

$stat = $db -> Execute("SELECT `id` FROM `players` WHERE `email`='".$_SESSION['email']."' AND `pass`='".$pass."'");

Tu uwaga: jeśli ktoś robił "poprawkę" bo miał "Sesję zakończoną" to najpewniej będzie wyglądać to tak:

$stat = $db -> Execute("SELECT `id` FROM `players` WHERE `email`='".$_SESSION['email']."'");

Do listy pól wyciąganych z bazy musimy dopisać lpv oraz każde inne pole z którego NIE JEST tworzony obiekt w player_class.php (chociaż go tam też można stworzyć). Szczególnie dotyczy tych co przez listę przekazują opisy!

Typowy kod po dodaniu pola lpv:

$stat = $db -> Execute("SELECT `id`, lpv FROM `players` WHERE `email`='".$_SESSION['email']."' AND `pass`='".$pass."'");

Następnie szukamy kilka linijek dalej:

$player = new Player($stat -> fields['id']);
$stat -> Close();



i pod nimi wstawiamy:

$memoryt = $db -> execute('UPDATE playerlist SET user="'.$player -> user.'", rank="'.$player -> rank.'", lpv='.$ctime.', lip=lip+1 WHERE id='.$player -> id);
$ilosct = mysql_affected_rows();

if($ilosct == 0)
{
    $db -> execute('INSERT INTO playerlist (id, user, rank, lpv) VALUES ('.$player -> id.', "'.$player -> user.'", "'.$player -> rank.'", '.$ctime.')');
}

Tu oczywiście edytujemy zarówno dla UPDATE'a jak i INSERTA własne pola!

Ponadto pojawia się tu wspomniane przy tworzeniu tabeli pole lip - otóż jego stworzenie i zwiększanie o 1 przy każdym UPDATE'cie jest celowe bo może dość do sytuacji że poleci UPDATE ale nie zaktualizuje żadnego pola przez co mysql_affected_rows (co prawda adodb posiada jakieś tam swoje Affected_Rows jednak u Mnie coś za bardzo ruszyć nie chciało...) zwróci zero a wtedy poleci INSERT i sprzeda nam errorek z DUPLICATE KEYem...


Następnie w zapytaniu w footer.php od listy graczy, czyli te wspomniane na początku:

$objQuery = $db -> Execute("SELECT id, user, rank FROM players WHERE lpv>=".$span." ORDER BY id ASC");

Zmieniamy nazwę tabeli z players na nasze playerlist oraz w resetach (małym, ale można też i w dużym) dodajemy:

$sdeltime = time() - 3600;
$db -> Execute('DELETE FROM playerlist WHERE lpv < '.$sdeltime);

po to by nam czyściło tabelkę z wpisów które ostatnią aktywność miały 30 min temu (by tabelka czasem nie zeżarła całego RAMu bo wtedy goście od hostu mogą nas wyrzucić na zbity pysk).

I to wszystko, mam tak u Siebie, tabelka ma ponad 15 pól, ponad 1000 graczy i średnio 30 online, cała zajmuje ok. 1,6mb z ~200rekordów.

P.S. Jeśli mamy listę graczy na str. głównej to też tam warto zmienić nazwę tabeli z players na playerlist.
P.S.2. Nie wiem czy czasem czegoś nie pominęłam.

Zgłoś swój pomysł na artykuł

Więcej w tym dziale Zobacz wszystkie