Jde o jeden z nejčastějších problémů s výkonností aplikace a zároveň obvykle jde o low hanging fruit, který lze snadno vyřešit. Jde o to, že žádost o provedení práce obvykle něco stojí a často to může být víc, než kolik stojí samotná práce. Platí to zejména tehdy, když práce obsahuje nějakou komunikaci po síti, např. databázový dotaz. Takže nemusí až tolik záležet na tom, jaké databázové dotazy kladete, ale kolik jich kladete.
Problém s tímto pravidlem je, že je obvykle mnohem jednodušší napsat přímočarý kód, který provádí práci hned, než kód, který práci dělá najednou. Porovnejte následující dvě ukázky:
<?php // provádění práce hned $articles = $db->query('SELECT * FROM article LIMIT 10'); foreach ($articles as $article) { $author = $db->query('SELECT * FROM author WHERE id = ?', $article['author_id'])->fetch(); } // provádění práce hromadně $articles = $db->query('SELECT * FROM article LIMIT 10'); $author_ids = array(); foreach ($articles as $article) { $author_ids[$article['author_id']] = null; } $authors = array(); if ($author_ids) { foreach ($db->query('SELECT * FROM author WHERE author_id IN (?)', array_keys($author_ids)) as $author) { $authors[$author['id']] = $author; } } foreach ($articles as $article) { $author = $authors[$article['author_id']]; } ?>
Správným řešením je opět použít vhodnou abstrakci, která špinavou práci provede za nás. Tento problém byl hlavní důvod, proč jsem vymyslel NotORM, kde se stejně efektivní kód dá napsat přímočarým a ještě jednodušším způsobem:
<?php $articles = $db->article()->limit(10); foreach ($articles as $article) { $author = $article->author; // provede jen jeden dotaz za celý cyklus } ?>
Tento problém se netýká zdaleka jen provádění databázových dotazů. Pokud třeba indexujete data do Elasticsearch, tak můžete index obnovit při každém zaindexovaném dokumentu nebo až v okamžiku, kdy zaindexujete všechny. Může jít třeba jen o jeden přesunutý řádek, který kód zrychlí tisícinásobně.
Stejně tak pokud třeba v JavaScriptu vytváříte HTML kód z fragmentů, tak můžete mnohokrát změnit innerHTML
(např. v jQuery metodou .after()). Nebo si fragmenty můžete naskládat do pole a to na konci zřetězit a do dokumentu vložit najednou. Opět jde o jednoduchou změnu, která výkonnost dramaticky vylepší.
Nevýhoda tohoto přístupu spočívá ve větším množství zabrané paměti, té je ale obvykle dost. Navíc když už je kód napsán správně, tak se to dá obvyle snadno regulovat, např. prostou změnou LIMIT 1000
na LIMIT 100
.
Přijďte si o tomto tématu popovídat na školení Výkonnost webových aplikací.
Diskuse je zrušena z důvodu spamu.