Cache dat z dotazů

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Mas3r
Člen | 116
+
0
-

Když jsem si teď projížděl SQL log z dibi, tak jsem objevil, že při 1 životním cyklu mám například 11 dotazů, z toho 3 jsou úplně identické.

  1. Výběr kategorií pro menu eshopu
  2. Výběr kategorií pro podkategorie v katalogu
  3. Výběr kategorií pro vyhledávač

Tak mě napadlo, že když to vraci úpně stejná data, tak by se ty data mohly někam ukládat a chytře rozšířená třída DibiTable by specifické dotazy mohla ukládat do cache a klíčem by byl samotný dotaz. Myslíte, že to má cenu? Když 1 dotaz trvá 0.5ms?

Jod
Člen | 701
+
0
-

Nepatrí toto do dibi fóra? David vravel, že dibiTable vyhodí z distribúcie, ak tak už nespravil. A keď robíš jeden select trikrát, tak si zoptimalizuj kód aplikácie.

Mas3r
Člen | 116
+
0
-

No je to dotaz nekde na pomezi Nette/Dibi… Zoptimalizovat: Právě nevím jak. Když ve 3 různých komponentách potřebuješ stejná data, tak je mezi těmi komponentami jednoduše sdílet?

Jan Tvrdík
Nette guru | 2595
+
0
-

Mas3r napsal(a):

No je to dotaz nekde na pomezi Nette/Dibi… Zoptimalizovat: Právě nevím jak. Když ve 3 různých komponentách potřebuješ stejná data, tak je mezi těmi komponentami jednoduše sdílet?

Komponenta požádá o data model a ten si je zapamatuje i pro další komponenty.

Mas3r
Člen | 116
+
0
-

Jo, to jsem měl na mysli s tím cachováním. Možná ukládat to do cache je hloupost, ale jak potom uložit ty data, když v komponentě volám novou instanci modelu? (Možná ty Vám ty dotazy přijdou hloupé, ale mějte se mnou trpělivost)

Honza Marek
Člen | 1664
+
0
-

Myslim, že to DibiDataSource by mohlo pomoct. Ale když trváš na tom, že stejnej dotaz musí vracet více metod, tak nevim.

PetrP
Člen | 587
+
0
-

Mas3r napsal(a):

…když v komponentě volám novou instanci modelu?…

Mít jen jednu instanci modelu? Udělat si třeba nějakou statickou továrničku na to.

onge
Člen | 53
+
0
-

Pokud pustis po sobe 3 identicke dotazky, tak si je interne cachuje uz SQL server (alespon MySQL to tak dela). Respektive nacachuje se dotaz, ne vysledky, ale pokud nectes tisice zaznamu, tak to stejne nevrati o moc pomaleji, nez by trvalo nejake cachovani v PHP (a nejspis sezere min pameti), protoze ten dotaz uz je zpracovany a rovnou se spousti.

Pokud tahas neco vetsiho, co budes potrebovat tak bych si ten vysledek proste ulozil do nejake promene a bral to z toho, nebo napsal metodu tak, aby to nacetla pouze jednou a ulozila. Kazdopadne resit tohle tak, ze by se cachovali vsechny SQL dotazy by dle meho nazoru neprineslo nic dobreho, spis by tim mohla zatez dokonce narust.

Jod
Člen | 701
+
0
-

Jj, toto je už otázka správneho návrhu aplikácie. Model si vytvor v presenteru a komponente ho predaj pomocou parametru. Alebo proste len zavolaj v componente $this->presenter->model, aj keď to neni najštastnejšie riešenie ))

Mas3r
Člen | 116
+
0
-

Onge: Máš pravdu MySQL a jiné dotazy cachují. Takže to asi velký smysl mít nebude.

No potřeboval jsem nějaké důvodi proti, abych se v tom nemusel rýpat :)

kravčo
Člen | 721
+
0
-

Mas3r napsal(a):

Když jsem si teď projížděl SQL log z dibi, tak jsem objevil, že při 1 životním cyklu mám například 11 dotazů, z toho 3 jsou úplně identické.

  1. Výběr kategorií pro menu eshopu
  2. Výběr kategorií pro podkategorie v katalogu
  3. Výběr kategorií pro vyhledávač

Tak mě napadlo, že když to vraci úpně stejná data, tak by se ty data mohly někam ukládat a chytře rozšířená třída DibiTable by specifické dotazy mohla ukládat do cache a klíčem by byl samotný dotaz. Myslíte, že to má cenu? Když 1 dotaz trvá 0.5ms?

Možno by bolo na mieste optimalizovať radšej návrh, ako kešovať dopyty, ktoré sa vykonajú viackrát. Čiže radšej nerozmýšľať, ako tie dopyty nakešovať, rozmýšľať prečo tam tie tri rovnaké dopyty mám a či mi nestačí len jeden vhodne umiestnený…

Jan Tvrdík napsal(a):

Komponenta požádá o data model a ten si je zapamatuje i pro další komponenty.

Toto je jeden z možných spôsobov, ako to vyriešiť, dáta sú potrebné na viacerých miestach, ťahajú sa z modelu a model si výsledok po prvom vyžiadaní zapamätá, teda pri ďalších požiadavkach na dáta neposiela dopyt na databázu, ale vráti zapamätaný výsledok.

pmg
Člen | 372
+
0
-

Pro použití jedné instance modelu je užitečné ho registrovat jako službu. Je to lepší než používat singleton, protože o použití sdílené instance rozhodne sama komponenta.

Environment::getServiceLocator()->addService(new Model($connection));

// v komponentě
$model = Environment::getService('Model');
phx
Člen | 651
+
0
-

Osobne model pouzivam jako jedinacka skrz celou aplikaci. Navic se mi ukazuje, ze pri jednoduchych dotazech e nacteni z DB zanedbatelne oproti samotnemu vykresleni napr do menu ci roletky:)

Osobne bych spise uvital kesovani napric requesty na app. Pri kazdem requestu nactiam menu, info o uzivateli a spol. Coz by teoreticky stacilo nacist pouze 1× pri prihlaseni. Otazka zni zda ma cenu takova data drzet v session. Zda by to melo vyznam. (vykonostni)

Jod
Člen | 701
+
0
-

pmg, budem asi musieť použiť tie service, kôli Acl, aby som tam dostal model.

phx, info o užívateľovi si ukladám do session a menu by som ukladal do cache v modelu. To je lepšie asi oblúžiť ručne než by to malo robiť nette zateba. Na toto mám jednu otázku.
Keď z modelu vraciam datasource a chcem dáta cachovať priamo v modeli a vracať buď datasource, alebo datasource aj s dátami, alebo nejakym spôsobom cachované dáta..nejak mi nenapadá ako nato. Možno by bolo dobré mať (ak to tam ešte neni) v datasouce udalosť onExecute, ktorá bude vraciať hodnoty z databázy, resp. datasource aj s načítanými dátami (sender) a celý object hodím do cache. Po načítani stránky zistím či objekt neni v cache, ak je vrátim cachovaný object s už načítanými dátami. V tomto prípade sa mi pozdáva aby si datasouce udržiaval dáta pčas svojej životnosti.

Ešte je tu možnosť používať cache helper v šablonách. Či to nebude jednoduchšie riešenie.

Ešte opravím tú registráciu service:

<?php
// mali by sme zadať service name ak nemáme len jeden model
Environment::getServiceLocator()->addService(new Model($connection), 'Model');
?>

Editoval Jod (22. 2. 2009 12:55)