Dibi versus Nette\Caching

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

Ahoj,
píšu si model-předka pro cachované SQL dotazy (až bude fungovat, zveřejním :)) a narazil jsem na problém, možná nedostatek Dibi nebo Nette\Cache, možná moji vlastní blbost.

Jde o to, že se v té mojí třídě volá metoda query a ta vrátí DibiResult – přesně jako Dibi. Tento DibiResult si vezme buďto přímo od Dibi a v případě, že existuje relevantní záznam v Cache, vezme si ho odtamtud.

Pokud si ho bere od Dibi (tj. v cache není), je vše v pořádku, pokud si daný DibiResult vezme z cache, už na něj nelze zavolat fetch() (a další související metody). Error, resp. warning je takovýto:

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/weby/www/Trance/libs/Dibi/drivers/mysql.php on line 368

A místo požadovaného DibiRow se v proměnné octne toto: bool(FALSE). Dělá to i s mysqli driverem.

Pokud dumpnu DibiResult od Dibi a z Cache, v sekci driver mi něco chybí. A v tom bude zakopaný pes :)

Dibi:

object(DibiResult) (6) {
  "driver" private => object(DibiMySqlDriver) (3) {
    "connection" private => resource of type(mysql link)
    "resultSet" private => resource of type(mysql result)
    "buffered" private => bool(TRUE)
  }
  "xlat" private => NULL
  "meta" private => NULL
  "fetched" private => bool(FALSE)
  "withTables" private => bool(FALSE)
  "class" private => string(7) "DibiRow"
}

Cache:

object(DibiResult) (6) {
  "driver" private => object(DibiMySqlDriver) (3) {
    "connection" private => int(0)
    "resultSet" private => int(0)
    "buffered" private => bool(TRUE)
  }
  "xlat" private => NULL
  "meta" private => NULL
  "fetched" private => bool(FALSE)
  "withTables" private => bool(FALSE)
  "class" private => string(7) "DibiRow"
}

Jak tedy data uložit do cache, aby zůstal celý objekt zachován? Teď to dělám takto:

$res = dibi::query($sql);
self::$cache->save(self::hashArray($args), $res, array(
       'expire' => time() + self::$expiration,
      ));
return $res; //zde je vše v pořádku, avšak to, co se uložilo do cache, už ne

Díky za každou radu.

LM
Člen | 206
+
0
-

Problém je že nelze serializovat proměnné typu resource (např. připojení k databází), což DibiResult v sobě uchovává, takže asi jen cachovat už fetchnuté data.

(možná by to chtělo v DibiResult nebo driverech zakázat (un)serializaci)

Ondřej Mirtes
Člen | 1536
+
0
-

LM napsal(a):

Problém je že nelze serializovat proměnné typu resource (např. připojení k databází), což DibiResult v sobě uchovává, takže asi jen cachovat už fetchnuté data.

(možná by to chtělo v DibiResult nebo driverech zakázat (un)serializaci)

Díky za info. Ale je to špatná zpráva, v téhle podobě by ten caching byl nejelegantnější. No, třeba ještě někoho napadne, co s tou nemožností serializace udělat.

EDIT: Tak jo, začal jsem cachovat až fetchnuté výsledky (dotaz na DB se vykoná až při zavolání fetch/fetchAll/fetchAssoc/fetchPairs, takže je to trochu více lazy) a funguje to jako po másle :)

Editoval LastHunter (12. 5. 2009 22:56)

kravčo
Člen | 721
+
0
-

Samozrejme musíš kešovať dáta, nie resourcy.

Dá sa to spraviť tak, že spravíš triedu CachedResult, ktorú naplníš pri dopyte na databázu dátami z výsledku a uložíš do keše. Aplikácii potom vždu podstrčíš len CachedResult, teda stačí implementovať metódy, ktoré využívaš (fetch(), …). Otázkou je, či je toto efektívny spôsob a či nie je nekešovaný dopyt (ktorý sa zrejme na db stroji aj tak kešuje) rýchlejší.

onge
Člen | 53
+
0
-

Pokud nekdy narazite na pripad, kdy tohle cachovani prinese s rozumne napsanym dotazem usporu v radech alespon desitek ms, dejte prosim vedet:)

Ondřej Mirtes
Člen | 1536
+
0
-

onge napsal(a):

Pokud nekdy narazite na pripad, kdy tohle cachovani prinese s rozumne napsanym dotazem usporu v radech alespon desitek ms, dejte prosim vedet:)

Viz toto vlákno. A při použití memcached to musí být ještě rapidně rychlejší.

onge
Člen | 53
+
0
-

S vypnutou cachi mas na mysli, ze smazes nacachovane soubory, nebo ze odstranis cachovaci kod? Pokud je to prvni pripad, pak bych ten rozdil chapal, ale pokud ten druhy, takhle mi to prijde ponekud zvlastni.

Pokud jde o memcache, tak to je trochu dvojsecna zbran a na cachovani vetsich dat (treba 500 000 radku z DB) se vyslovene nehodi

Ondřej Mirtes
Člen | 1536
+
0
-

onge napsal(a):

S vypnutou cachi mas na mysli, ze smazes nacachovane soubory, nebo ze odstranis cachovaci kod? Pokud je to prvni pripad, pak bych ten rozdil chapal, ale pokud ten druhy, takhle mi to prijde ponekud zvlastni.

Při tom testování jsem zakomentoval kód, který to ukládal do cache.

Pokud jde o memcache, tak to je trochu dvojsecna zbran a na cachovani vetsich dat (treba 500 000 radku z DB) se vyslovene nehodi

Jasně, to chápu, RAMka není nafukovací. A pro načítání 500k řádků využití nemám. Spíš to cachování využiju na nějaké komplexní navštěvované homepage, kde se načítají články, aktuality, uživatelé, nejnovější thready z fóra… to DB serveru odlehčí.

Myslel jsem, že cachování DB dotazů na disk/do mem je takový standard a hle – já si ho tu ještě musím obhajovat. Vždyť dotazy na DB je to úzké místo aplikace, kde se jimi vyplatí šetřit a odlehčit DB serveru – který navíc ani nemusí být na tom samém stroji, ale komunikace s ním probíhá přes síť. Nebo se mýlím?

onge
Člen | 53
+
0
-

Chapu to tedy spravne, ze jsi zakomentoval tuhle cast?

$this->cache->save($this->hash."-".$mode, $res, array(
    'expire' => time() + $this->expiration,
));

No, standardni je kesovat vystup, ne vysledky dotazu, ze kterych se pak ten vystup generuje. To vlastne resi i to, ze se nemusis dotazovat na databazi. Zatim jsem se nesetkal s tim, ze by databazovy server – i kdyz bezi na jinem stroji – mel tak dlouhe odezvy, ze by stalo za to kesovat specificky jen dotazy. Mohlo by to mit smysl v pripade, ze si hosting do trafiku pocita i komunikaci s databazi, ale osobne bych v takovem pripade uvazoval spis o zmene hostingu:)

I tak si ale nedokazu predstavit pripad, kdy by se mel cachovat vysledek z DB, ale nedal se cachovat vystup.

Editoval onge (15. 5. 2009 14:46)