Několika způsoby lze PHP + MySQL zrychlit až dramaticky. Dnes si je rozebereme.
1.9.2004 15:00 | Petr Zajíc | přečteno 45795×
V minulém díle jsme si ukázali, jak zrychlit práci s PHP a MySQL pomocí rozumně tvořených dotazů, správného využití agregačních funkcí a přenesení výpočtů na databáze. Dnes se podíváme na zbytek "zrychlovacích" triků.
Jestliže použijete pro otevření databázového spojení funkci mysql_pconnect namísto mysql_connect, bude vytvořeno (nebo použito již dříve vytvořené) perzistentní spojení. Toto spojení může PHP použít napříč několika skripty, takže můžete ušetřit čas potřebný pro otevírání druhého a dalšího spojení.
Pozn.: Tento čas může být poměrně
dlouhý, zejména pokud MySQL běží na jiném stroji než PHP.
Perzistentní spojení bude fungovat pouze v případě, že bude PHP spuštěno jako modul Apache. Neušetří samozřejmě žádný další čas při provádění skriptu kromě času při opakovaném přihlášení. Ale i to může být někdy dost.
Tato PHP funkce je shodná s funkcí mysql_query s tím rozdílem, že nečeká na načtení všech záznamů z dotazu SELECT předtím, než je začnete zpracovávat. To se může v případě velkých sad záznamů docela hodit. Pamatujte ovšem na to, že to má rovněž následující omezení:
Uvědomte si rovněž, že to je funkce PHP, ne MySQL. V praxi to znamená, že PHP může dělat další věci (například, vypisovat již získaná data do prohlížeče zatímco "přitékají" další data). Pro chudáka MySQL se použitím mysql_unbuffered_query nic nemění, ta musí udělat stejnou práci jako kdybychom použili mysql_query.
Většinu databázové práce lze urychlit správným použitím indexů. Index je pomocná datová struktura, která zachycuje vztah mezi hodnotou záznamu ve sloupci a jeho fyzickým umístěním v tabulce. Například, jestliže si vzpomenete na náš příklad z dílu o vyhledávání obcí podle PSČ, byla tam použita tabulka se dvěma poli - "obec" a "psc". Jelikož byla tabulka seřazena podle obcí, nezbylo nebohému databázovému stroji při požadavku najít obce s určitým PSČ nic jiného, než celou tabulku projít. To bychom mu mohli ulehčit vytvořením indexu na poli psc. Odpovídající příkaz jazyka SQL zní:
ALTER TABLE `psc` ADD
INDEX ( `psc` )
V případě, že index na sloupci psc bude skutečně existovat, bude nalezení odpovídajících záznamů mnohem rychlejší. Aby nám MySQL trochu ulehčila práci s odhadováním, jak bude dotaz probíhat, je k dispozici SQL příkaz EXPLAIN. Ten nám poskytne potřebné informace. Tak napříkad
EXPLAIN SELECT * FROM
`psc` WHERE psc=46001
na tabulce bez indexů vrátí následující údaje:
table | type | possible_keys | key | key_len | ref | rows | Extra |
psc | ALL | NULL | NULL | NULL | NULL | 16905 | Using where |
po přidání indexu to už bude mnohem nadějnější:
table | type | possible_keys | key | key_len | ref | rows | Extra |
psc | ref | psc | psc | 5 | const | 48 | Using where |
Aniž bychom nějak extra rozebírali informace vrácené pomocí EXPLAIN
uveďme, že sloupec rows uvádí počet řádků, které bude muset MySQL
projít, aby nám mohla naservírovat výsledek dotazu. Po vytvoření indexu
to bude jen zlomek z celkového počtu řádků a prostým rozumem dojdeme k
tomu, že to bude rychlejší.
Ovšem pozor - bylo by snadné si myslet, že stačí oindexovat všechna
pole a databáze se zrychlí. Tak to není; ve skutečnosti údržba indexů
vyžaduje rovněž nějaký čas. Při jakékoli změně dat musí být indexy
rovněž upraveny. Obecně se to dá formulovat tak, že indexy ZRYCHLUJÍ
výběrové dotazy (SELECT), ale zpomalují dotazy manipulační (INSERT,
UPDATE, DELETE, REPLACE). Protože v příkladu byla databáze určena jen
pro čtení, bylo by použití indexů svrchovaně na místě.
Jestliže změníme v MySQL strukturu indexů, je vhodné použít příkaz ANALYZE
TABLE. Jenž si, česky řečeno, udělá pořádek v indexech tabulky a
bude napříště vědět, které indexy a v jakém pořadí pro obsluhu dotazů
použije.
MySQL má příkaz OPTIMIZE
TABLE. Ten dělá to, že fyzicky porovná datové struktury na disku a
charakterem připomíná defragmentaci souborů souborového systému.
Dokumentace upozorňuje, že ve většině případů nebude nutné jej
spouštět; svoje uplatnění najde zejména tehdy, pokud jsme prováděli
rozsáhlé promazávání nebo úpravy polí proměnné délky.
Rychlost databáze se dá ovlivnit tím, že používáme správné a nejkratší možné typy sloupců na uložení odpovídajících dat. MySQL má docela užitečné rozšíření spočívající v tom, že existuje následující nástroj: Příkaz SQL, který projde tabulku a na základě dat v ní navrhne případné změny v její definici. Příkaz vypadá následovně:
SELECT * FROM `psc`
PROCEDURE ANALYSE ( )
a v našem případě by nám vrátil zhruba toto (některé sloupce
výsledku jsem vynechal):
Field_name | Min_length | Max_length | Empties_or_zeros | Nulls | Optimal_fieldtype |
psc.obec | 3 | 47 | 1 | 0 | VARCHAR(47) NOT NULL |
psc.psc | 5 | 5 | 0 | 1 | MEDIUMINT(5) UNSIGNED |
Užitečnost tohoto přístupu je sporná - na jedné straně nám to umožní smrsknout definici na co "nejužší" sloupce; na straně druhé nám to trochu svazuje ruce a dá se to provést pouze na naplněné tabulce. V našem případě by z toho vyplývalo jediné - jelikož asi nevznikne na území ČR obec s názvem delším než 47 znaků, mohli bychom směle zkrátit maximální délku názvu obce z 60 znaků na 47.