Vyplatí se cachování výsledků SQL dotazů?
- ondrej256
- Člen | 187
Zdravím,
chtěl bych se zeptat zda se vyplatí cachovat výsledky SQL dotazů.
Například mám menu, po kliknutí na položku menu se vyrolují jeho
podpoložky (podpoložky se NEnačítají ajaxově).
Takže při každém requestu na web posílám dotaz do DB, kde si vytahuju celé menu a pak ho vykresluju.
Nemůžu cachovat přímo HTML, protože se k položce menu připíše třeba „class: active“ apod. Takže bych musel cachovat strašně moc kombinací.
Proto chci cachovat pole, kde mám uložená veškerá data (položky menu).
Bral jsem jako samozřejmost, že je rychlejší to takto cachovat, ale zjistil jsem, že vlastně nevím proč. Chtěl bych se zeptat co si o tom myslíte vy a jak by jste si odůvodnili, že je to rychlejší.
Za sebe mám maximálně jeden argument:
- ušetřím čas, kdy posílám po síti dotaz na databázový server (což nemusí být vždy pravda, někdy je apacha i mysql na jenom stroji)
- MirekTH
- Člen | 20
Nejlepší je psát aplikaci tak, aby cache na této úrovni nebyla potřeba. Při použití cache totiž nastává problém s její invalidací a zbytečně se do aplikace zatahuje další logika. Pokud už na tohle používáš cache tak vyber správný storage (na tyhle cache je ideální memcache nebo redis). Každopádně těžko radit zda se to v tvém případě vyplatí. Je to vždy o méření a to si musíš provést sám.
- Azathoth
- Člen | 495
Cacheování je zapotřebí vždycky měřit, a podle výsledků měření se
rozhodnout, jestli se to vyplatí nebo ne.
Udělej si několik měření, jak rychlé to máš bez cache a s cache. Já
jsem na jednom projektu cacheoval až ve chvíli, kdy mi to stlačilo page load
o několik desítek procent.
Souhlasím, že ideální je psát tak, aby nebylo cache zapotřebí, ale někdy
je cache ta nejschůdnější možnost.
- MirekTH
- Člen | 20
Cache je vždy pouze jedna z částí optimalizace, lidé jí ale často berou jako spásu – nemusím se babrat s indexy nebo vymýšlet optimální strukturu, nějak to nabastlím a pokud to bude pomalé tak tam frknu cache a ono to nějak dopadne. Což je hlavní problém a často se cache objevuje tam, kde být vůbec nemusí.
Na této úrovni ji nasazuji pouze u starších projektů nebo monolitů, kde optimalizace kódů může zabrat zbytečně moc peněz a času, takže se cache pak vyplatí. Na invalidaci se pak celkem dobře dají použít Kdyby\Events – pokud přidám záznam, upravím záznam atp … tak invaliduji cache přes určitý tag. U nvých projektů a projektů, kde mi to struktura aplikace dovolí, raději optimalizuji jednotlivé části kódu a cache pak není na této úrovní vůbec potřeba.
Tím jsem jen chtěl říci, že to není černobílé a nejde s jistotou říct, kdy cache použít a kdy ne. Někdy se vyplatí a někdy je naprosto zbytečná, pomalejší a nebo kontraproduktivní.
- Azathoth
- Člen | 495
Správná úroveň je podle mne dělat cache tam, kde by se těch samých
dotazů opravdu hodně opakovalo a ta data, po kterých se ptáš, se moc často
nemění v poměru k tomu, kolikrát se na ně ptáš). Tedy například pokud
budeš mít na homepage sloupek s novinkami, které jsou stejné a musí se
načítat pořád stejně pro všechny a ten SQL dotaz je složitý, tak se
rozhodně vyplatí to cacheovat.
Pokud bys chtěl cacheovat například výsledek SQL dotazu pro přihlašování
uživatele, tak tam se to cacheovat nevyplatí.
Musíš zvážit, jak často se ten samý dotaz vykonává a jak je důležité
mít rychle načtenou stránku (např. homepage by měl být rychlý,
přihlášení tak rychlé být nemusí).
Nadhoď, pro jakou aplikaci to řešíš, jaké dotazy by tam byly, kde myslíš, že by byly bottlenecky a můžeme to řešit konkrétně.
- blaztar
- Člen | 93
No třeba uvedený příklad autora příspěvku. Hlavní menu stránky.
Myslím že často se nemění, a zároveň správné vytvoření stromu pro výpis podpoložek apod. může být celkem náročné ne?
edit: Je teda pravda že většinou mám jedno max dvě zanoření..
Editoval blaztar (7. 3. 2016 15:02)
- MirekTH
- Člen | 20
Může i nemusí. Pokud máš dotaz „SELECT id, name, url FROM products INNER JOIN products_categories ON (…)“, máš pár kategorií a nic dalšího tak se cache nevyplatí. Pokud tam máš složitější výpočty a nelze se k nim dostat jiným, rychlejším způsobem (druhý dotaz, optimalizace indexu atd …) a nelze to zoptimalizovat jinak, použij cache a pořádné popřemýšlej, kde všude bude potřeba cache invalidovat.
Já se ale zbytečné cache vyhýbám jak jen to jde. Vem si třeba příklad:
Začneš výsledek cachovat. Vše je ok, ale za měsíc přijde klient, že by u každé kategorie uváděl v závorce počet produktů, které tam jsou. Budeš mít v podstatě tři možnosti – zoptimalizovat to jinak a cache vyhodit, invalidovat cache při každém přidání produktu a nebo klienta seznámit s tím, že cache se invaliduje při změně kategorie a nebo 1× za hodinu. 1 je ok, 2 je zbytečná práce a logika navíc (nemluvě pokud zakládáš produkty často), u 3ky zase vypadáš jak amatér. Takovýchto případů je více. Proto mám raději jiný způsob optimalizace.
- blaztar
- Člen | 93
Konkrétní moje situace.
Používám NTDB. Tabulky v db mají často složený primární klič (typicky ID, LANG). Podle dokumentace myslím, že tím u mě padá nějaká možnost velkého joinování apod. Dál s daty ještě trošku pracuji (převod na pole a doplnění nějakých dat).
No půjdu měřit a uvidím.
- blaztar
- Člen | 93
Moje výsledky (tuším že bez kódu apod to asi není moc užitečný)
V kódu:
s: 0.0177321434021, 0.018841981887817, 0.026428937911987, 0.02350902557373, 0.017003059387207
bez: 0.046530961990356, 0.048104047775269, 0.053776979446411, 0.05233097076416, 0.051090002059937
V šabloně:
s: 0.0011250972747803, 0.00094294548034668, 0.0010149478912354, 0.0012729167938232, 0.0012722015380859
bez: 0.035425901412964, 0.038606882095337, 0.045409917831421, 0.044508934020996, 0.044265031814575
Editoval blaztar (7. 3. 2016 15:53)