Kdy cachovat data? (MySQL) rubrika: Programování: PHP

Anonym
položil/-a 22.9.2015

Dobrý den,

mám aplikaci v Nette, a zatím to mám udělané tak, že výsledky více než 3/4 dotazů do databáze, ukládám do cache. To znamená, že třeba seznam uživatelů načtu jen jednou, uložím do cache, a při příštím volání už načtu z cache.
Co se týká aktualnosti dat - tak nad tabulkama v databázi mám zavěšené triggery, které hlídají změny v tabulkách, a v případě změny pročistím cachované data, aby se znovu načetly, a byly vždy aktuální.
Podařilo se mi díky tomu zredukovat počet dotazů do databáze na méně než čtvrtinu.

Má otázka je, zda je to vhodné řešení, a nebo je to už moc přehnané? Budu rád, kdybyste se někdo rozepsal o svých zkušenostech s cachováním databáze, apod.

Občas se mi stane, že tahám z db/cache, jen jeden řádek - a tak si říkám, zda už nebude rychlejší ten jeden řádek načíst přímo z té databáze, než to tahat z cache.
Jinak - cache se ukládá do json souborů.

Web ještě není spuštěný, ale očekává se průměrná zátěž 500-1000 lidí denně, z různých míst po celé Evropě.

Díky

Komentáře

  • Anonym : pokud ti tam přijde 1 člověk za 2 minuty či za minutu, tak spíš cachuj výsledek celého zpracování, nikoliv dB výsledky :D předně bych pak optimalizoval strukturu webu, využití CDN, kompilace CSS atd. = možná se snažíš zvýšit rychlost na nesprávném místě 28.9.2015
  • Občan : @Fred Brooker: Souhlas celý výsledek. Cachovat opačnou stranu, safe requesty u výstupu. 29.9.2015
odkaz
12 Kit
odpověděl/-a 23.9.2015

Podle popisu jen zbytečně duplikuješ cache, kterou má v sobě už samotná databáze - navíc v mnohem lepší kvalitě. Počet dotazů do DB nejlépe zredukuješ tak, že zlepšíš jejich kvalitu. Zásadní chybou je například umístění databázového dotazu do jakéhokoli cyklu. Pokud tam něco takového máš, zbav se té své vlastní cache a vyřeš si nejprve problém s tím cyklem. Uvidíš, že tím té své databázi prospěješ mnohem víc než nějakým duplicitním cachováním.

Komentáře

  • rmaslo : Naprostý souhlas, db to bude mít určitě vyřešeno líp než to uděláš. Jen k db cache bych ještě dodal, že pro ní "SELECT x from y" a "SELECT x FROM y" jsou dva různé dotazy. Takže je dobré psát ty dotazy stejným způsobem (malá x velká, mezery, atd...) nebo si je dát rovnou do view. 23.9.2015
  • Kit : @rmaslo: To s tou velikostí písmen jsem si dosud neuvědomil. Při prototypování sice běžně používám malá písmena, ale do finálního řešení je vždy konvertuji na velká. Dělám to tak spíš kvůli "štábní kultuře", ale evidentně to má vliv i na cache. Nevzpomínám si však, že bych v nějaké aplikaci měl dva stejné SQL dotazy. Podobný vliv jistě bude mít označení `identifikátoru`, "identifikátoru" a identifikátoru. Samozřejmě mám nejraději poslední variantu, protože je IMHO nejpřehlednější, ale bohužel se nedá použít u generátorů dotazů. 23.9.2015
  • pavel.stehule : Ona MySQL cache výsledků je docela hloupá, a pokud má nízké hitratio, tak je i kontraproduktivní. Důležitější je cache datových stránek, aby se zbytečně nelezlo na disk (případně se zbytečně nevolal systém), a to dnešní databáze mají už dobře vyřešené (InnoDB ano, MyISAM ne, Postgres ano,..). Naplánování a exekuce dotazu je v databázích do 1-2GB pár ms. Paměťové cache je dobré používat v rámci session, určitě stránky. Pokud při rendrování pošlu do databáze Nkrát stejný dotaz, tak MySQL result cache mi pomůže, ale stejně zbytečně dosuji databázi, a je lepší si výsledek uložit do proměnné, a neposílat zbytečně dotaz. 23.9.2015
  • rmaslo : @Kit: jj rozlišuje. Já na to přišel až u MariaDB, kdy jsem zapnul SET optimizer_switch = "derived_merge=off" a ono to vypadalo, že to nic nedělá. Pak jsem napsal ten dotaz trochu jinou velikostí písmen a najednou to fungovalo. Takže jsme zjistil, že nastavení tohoto switche nevymaže cache a že cache je přímo na stringový tvar SQL. Stejné dotazy se dost vyskytují při plnění komb z číselníků, kdy daný číselník je použit pro více tabulek. 23.9.2015
  • rmaslo : @pavel.stehule: Souhlas, paměťové cache uvnitř stránky samozřejmě ano. PS: Co to je "dosuje"?, to jsem nikdy neslyšel. 23.9.2015
  • pavel.stehule : @rmaslo: česká odvozenina od "Denial of Service" - zbytečné SQL dotazy ~ vlastní DOS útok 23.9.2015
  • rmaslo : @pavel.stehule: Jasný už chápu... :-) 23.9.2015
  • Kit : @rmaslo: Číselníky zpravidla joinuji do dotazu, proto se s tím nesetkávám. Mnoho číselníků mám také přímo ve výstupních šablonách nebo přidružených XML. Zejména těch jazykově závislých. 23.9.2015
  • rmaslo : @Kit: Souhlas, na výstupu se většinou číselníky joinují. Ale na vstupu (editace záznamu) jsou komba. Zrovna tady mám nějaký program pro malou výrobní firmu. Zdroj komba pro výběr pracovníka (tj. něco jako SELECT id, CONCAT_WS(" ",prijmeni,jmeno) AS neco FROM ... ORDER BY neco) je použit pro pole z tabulky zakázka: zakazku_kalkuloval, zakazka_mistr, paragon_vydal, dále v rozpisu zakázky pro: výroba_pridelena, pak je nějaká tabulka pro posílání zpráv: od_koho, komu a ještě asi dalších 10 míst. S trochou fantazie bych ten dotaz mohl na každém místě zformátovat/zapsat o něco jinak. 23.9.2015
  • Kit : @rmaslo: Tohle jsem kdysi také zkoušel do doby, než mi to na abclinuxu.cz omlátili o hlavu. Daleko užitečnější se mi ukázalo, když jsem udělal " SELECT id, prijmeni, jmeno FROM ..." a spojil to až ve výstupní šabloně. Místo "$kalkuloval->neco" jsem do šablony dal "$kalkuloval->jmeno $kalkuloval->prijmeni" a bylo to. 23.9.2015
  • rmaslo : Čím to na abclinuxu zdůvodňovali? Já si zcela naopak myslím, že by to spojení stringů mělo být "centrálně řízené" tj. mělo by to být třeba ve View. Důvod - až přijmou dva "Jan Novák" tak se jen do db přidá třetí sloupec "přezdívka" a změní se to View - což se promítne do všech komb a nebudu muset měnit kód+šablonu na 15-ti různých místech. 23.9.2015
  • Kit : @rmaslo: Zdůvodnili to tím, že porušuji zodpovědnosti v jednotlivých vrstvách. Formátování výstupu nepatří do modelu, ale do view. 23.9.2015
  • Kit : @rmaslo: Koukám, že to máš naopak: SQL dotazy ve view. Tak to nedělám, protože můj view nemá přístup k databázi a ani nemá komu poslat SQL dotaz. Vlastně ani nemá tušení, že existuje nějaká DB a kde ta požadovaná data vlastně jsou. Jestli v DB, FS nebo v cloudu - to ví jen model, který to nikomu neřekne. 23.9.2015
  • rmaslo : @Kit: Blbě jsi to pochopil nebo já to blbě napsal. NEmyslím View ve smyslu MVC, ale View ve smyslu db View (pohled) - že bych si prostě ten dotaz pro to kombo uložil do db. S tím že formátování výstupu nepatří do modelu zcela souhlasím. Ale naopak si myslím, že do modelu patří definice jednoznačného "Human key" tj. klíče pro lidi. Já to tedy neberu jako nějaký zformátovaný string pro výstup, ale jako dvojici PK, HK. 23.9.2015
  • Kit : @rmaslo: No jo, není pohled jako pohled :) 23.9.2015
  • nov.ondrej : Nevím jak je to teď, ale ještě nedávno MySQL neumělo cachovat prepared statements. Dotaz musí být poslán již vyplněný. 25.9.2015
  • vojtech.kurka : MySQL to umi, ale jen v ramci jednoho spojeni. Prepared statements ale nekompiluje, takze prakticky v MySQL nemaji (vykonnostni) opodstatneni. 25.9.2015
  • Kit : @nov.ondrej: Když se podíváš, jak je realizováno prepare() a execute() v PDO, tak zjistíš, že se dotaz pouze kompletuje a posílá na server včetně dat - tedy jako jediný dotaz. Pokud chceš reálné prepared statements, musíš tuto emulaci v PDO vypnout. Zpravidla je však výhodnější nechat tuto emulaci zapnutou a prepared statements normálně používat. SQL dotazy jsou totiž s nimi mnohem čitelnější a zpravidla je můžeš mít i v konstantách tříd. 25.9.2015
  • Kit : @nov.ondrej: Pokud potřebuješ pracovat s dlouhými SQL dotazy, můžeš si je na server uložit jako procedury ve zkompilované podobě, resp. ve formě pohledů či triggerů. Používám to zejména tam, kde různí klienti mají různé požadavky na vnitřní strukturu dat, ale aplikaci chci mít jednotnou pro všechny. Snáze se tak udržuje a neuděláš chybu při distribuci záplat. 25.9.2015
  • nov.ondrej : Já se omlouvám, ale domníval jsem se, že jde o diskuzi o cache v MySQL, nevím co s tím má společného PDO. Že PDO emuluje prepare je věc jiná. Osobně častěji používám MySQL z C++. 26.9.2015
  • Kit : @nov.ondrej: Rubrika se jmenuje Programování: PHP. PDO je jeho ovladačem databází. Ta emulace prepare() se obvykle hodí, protože zvyšuje výkon. Je jen pár okrajových případů, kdy je nutné tuto emulaci vypnout. 26.9.2015

Pro zobrazení všech 8 odpovědí se prosím přihlaste:

Rychlé přihlášení přes sociální sítě:

Nebo se přihlaste jménem a heslem:

Zadejte prosím svou e-mailovou adresu.
Zadejte své heslo.