Diskuze: Doctrine snížení počtu dotazu
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.
Tvůrce
Zobrazeno 15 zpráv z 15.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.
Rekurzi asi moc efektivně v databázi neuděláš, nestačilo by to jen cachovat? My tohle většinou řešíme tak, že se zacachují všechny položky a ten strom se potom prochází na serveru, aby se na to nemuselo ptát databáze.
No, lámu si s tím hlavu už 2 dny a níž jak na 12 dotazu to nesnížím.
Jinak dobrej nápad s cachováním, aspoň to nebude zatěžovat DB. Díky
12 dotazů nějakými cykly nad polem v paměti je úplně v pohodě, to je hned. Na databázi je to horší Cachuj to už jako strom (pole polí polí...), aby to bylo rychlejší.
koukam, ze se mi nekdo strefil do meho oblibeneho tematu
tipuju, ze si u kazde polozky zbozi nebo kategorie ukladas id rodicovske kategorie
navrhuju uplne jiny model, ktery jsem zatim neimplementoval v doctrine, ale v obyc. SQL jsem v tom implemetoval stromecek kategorii v helpu jedne webove aplikace plus editor toho stromecku
misto id rodicovske kategorie si u kazde kategorie ukladej do jednoho varchar
sloupce cestu
ale tak, aby kazda polozka cesty mela max. rekneme 4 znaky (tedy maximum 9999
kategorii v databazi)
muze se zvysit treba na 5 (potom je maximum kategorii 99999) a tak dal.
priklad:
id: 1
cesta: ''
id: 20
cesta: '0001'
id: 35
cesta: '0001/0020'
id: 36
cesta: '0001/0020'
1 - Všechno Zboží
20 - Laptop
35 - Apple
36 - Microsoft
sloupec cesta by mel byt varchar(255) a samozrejme tam existuje omezeni v hloubce stromu
v pripade 255 znaku a 4-mistneho id kategorie je to 255 / 5 = 51 (51 levelu
stromu je dost na eshop )
v pripade 255 znaku a 5-mistneho id kategorie je to 255 / 6 = 42.5 ~ 42 (42
levelu stromu je porad jeste az az )
v pripade 255 znaku a 6-mistneho id kategorie je to 255 / 7 = 36.43 ~ 36 (36
levelu stromu je furt vic nez dost )
v pripade implementace Amazonu s miliardami polozek zbozi by snad slo strom prohloubit pouzitim dvou sloupcu misto jednoho ale myslim, ze mozna ani Amazon by toto nevyuzil
samotne polozky zbozi uz muzou mit jen id rodicovske kategorie a veskere dotazy se vyresi joinem k patricnym kategoriim
diky pevne sirce id kategorie (4, 5 nebo 6) muzes vybrat vsechny laptopy Apple a Microsoft jednoduse nejak takto:
SELECT
*
FROM
kategorie as k,
zbozi as z
WHERE
(
k.id IN (35,36)
OR LEFT(k.cesta, 14) = '0001/0020/0035'
OR LEFT(k.cesta, 14) = '0001/0020/0036'
)
AND
z.kategorie_id=k.id
coz ti vybere vsechny kategorie, ktere jsou Apple a Microsoft a nebo maji Apple a Microsoft za rodice, prarodice, prapra... atd.
joinem se k tomu pripoji veskere zbozi ve vybranych kategoriich a mas vystarano
otazka zni, jak na to v doctrine
sloupec z. kategorie_id neni problem ... entita Zbozi proste obsahuje vztahovou property $kategorie
sloupec k.cesta ($cesta v entite Kategorie) ale doctrine nerika nic o vztahu kategorie a zbozi
muze se ale pouzit DQL, misto funkce LEFT pouzit SUBSTRING a tim kategorie vybrat a omezit jimi vyber zbozi nejak takto:
$query = $em->createQuery("SELECT z FROM Zbozi z JOIN z.kategorie k WHERE k.id IN (35,36)
OR SUBSTRING(k.cesta,0,14) = '0001/0020/0035'
OR SUBSTRING(k.cesta,0,14) = '0001/0020/0036'");
$users = $query->getResult();
je to jen nastrel myslenky a potrebuje to poradne vychytat
ale vysledek usilovne prace muze byt pouhy jediny dotaz
pokud budes implementovat aj editor toho stromu, tak se priprav na matematiku a debugging zahul v podobe prace s retezci v databazi
ale da se to, pokud te takove vyzvy bavi a pokud pouzijes mnou navrhovana cisla kategorii s pevnou sirkou s uvodnimi nulami
jenom pri te editaci stromu, pro jistotu pouzivat transakce/zamky nebo aspon zalohy kategorii&zbozi pred kazdou modifikaci stromu ... neni moc dobre v pripade bugu mit strom rozmrveny a majitele eshopu vytoceneho do bela ...
tady jsou slidy, ktere shrnuji praci se stromy v SQL, ruzne modely krome mnou zmineneho a zakladni operace v techto modelech
https://www.slideshare.net/…a-structures
dalsich takovych navodu je na webu spousta, staci vybrat model stromu, googlit a prevest SQL do Doctrine
To mi přijde jako poněkud nešťastné řešení, jakou má přidanou hodnotu oproti cache všech kategorií, co jsem navrhoval výše? Kromě toho, že je vážně pracné, představ si, že přesuneš nějakou položku do jiné kategorie. Rázem máš nekonzistentní databázi, protože ten string se neaktualizuje, musí se to dělat zvlášť nebo přes triggery. To je zdroj chyb. Obecně ukládat čísla jako stringy je špatná praktika, IMHO je ten model antipattern, ta databáze by měla být navržená rozumně.
nekonzistenci je samozrejme treba osetrit triggerem, jak pises nebo dvema dotazy v transakci jak rikas
co se tyce rychlosti ... editace stromu se dela jednou za cas ... pri cteni staci jedna rychla query s jednim joinem
navic cestu obsahuji jen kategorie, zbozi ma uz primo id kategorie, takze presuny zbozi mezi kategoriemi jsou otazkou jednoho dotazu
samozrejme php soubor s velkym oklicovanym polem kategorii nacachovany pomoci opcache bude rychlej jak vystrasenej pes oproti databazi ...
jenom si nejsem uplne jisty, jak zajistit 100% atomicitu operaci na dvema ulozisti zaraz (php cache, databaze) ... tedy treba odstraneni kategorie vcetne jejicho zbozi
tedy jak zajistim, aby v pripade nejakeho nenadaleho vypadku hw operace nezustala dokoncena jen v jednom z ulozist
nerikam ze to nejde, ale zatim, jedine , co me napada, je pouzit me reseni a pak po kazde modifikujici operaci udelat cache do php souboru
tim se spoji vyhoda atomicity databazovych operaci s rychlosti tveho reseni
ale jestli existuje zpusob, jak zajistit transakci nad databazi a tim php polem zaroven, bude mi i pro mou praxi velkym potesenim ...
Opcache jsou jen k ukládání mezikódu PHP pokud vím, nedají se tam cachovat vlastní hodnoty. My tohle ukládáme normálně do souboru. Načtení všech kategorií z databáze není tak drahá operace, cache se může dát nějaký lifetime, třeba několik minut nebo hodin, záleží na projektu. Potom se nekonzistence vyřeší sama, když něco spadne a někdo by cache potom zapomněl smazat, tak tam bude jen chvíli neexistující kategorie, než sama zmizí. Nevím, jestli by se vůbec měla řešit nějaká "transakce", specifikum cache je, že to není trvalé úložiště a tam tolik nevadí, když to je nekonzistentní.
jeste se nabizi partikularni reseni v podobe vynechani potencialne nebezpecnych operaci ... tedy tech, ktere potrebuji zaraz zapsat do obou ulozist
mam ale ted hroznej hlad, takze se nad tim zamyslim pozdejc, teda jestli me nekdo nepredbehne ...
jejda, nejak jsem nereloadoval a tudiz necetl posledni reakci
už to chápu ... takže v databazi to zůstane pomalé, ale snazší na implementaci
a rychlost se vyřeší pouze pomocí pravidelneho nacachovani v php souboru ...
jj, to je fikané a reálně funkční ...
jenom me irituje, že tam může bejt chvíli vidět něco, co tam už nemá bejt
spis bych tu cache obnovoval pouze po kazde modifikaci stromu v db ... tak casto se strom nemodifikuje v eshopech, co vim
pak by zmizel aj problem se zustavanim neceho, co uz neni
a to moje databazove rychlejsi reseni pak uz nebude potreba
jeste k te opcache .... ta si nahraje do RAMky kazdej php soubor, kterej php nacita/interpretuje
tedy aj ten s tema kategoriema
jenom v nejrychlejsi podobe konfigurace opcache nekontroluje data modifikaci souboru, aby je znovu nacetla do RAM
potom je treba pouzit na ten php soubor nasledujici funkci a reseni bude dokonale rychle
Ta cache se samozřejmě invaliduje někde v administračním rozhraní, kde se maže/mění/přidává kategorie. Výhodou toho řešení je, že i když se nesmaže (to se prostě stát může třeba výpadkem), tak stejně po nějaké době expiruje. O té opcache si nejsem jistý, jestli ti pomůže, IMHO to cachuje mezikód, tady by se spíš hodilo Memcached http://php.net/…emcached.php . My to serializujeme do souboru a funguje to skvěle, to je nejjednodušší řešení, jen se nesmí zapomenout správně zamknout.
ta opcache pomuze pokud v tom souboru je php kod s tim polem ... nehlede na to, ze pro molochy typu symfony podstatne zrychli celou aplikaci
memcached je spis na vyplivnuti hotoveho predpocitaneho vystupu v html, txt apod
pokud je v te cache pole, ve kterem se kod hrabe pri vyhledavani, pak opcache
pokud je tam predrenderovany vypis, tak memcached
ale tazatel co vim chce vyhledavat v poli konkretni id kategorii a podle nich pak vytahnout polozky zbozi
takze tady pomuze mit zaplou opcache ... pro celou aplikaci vcetne tohoto souboru
jen je treba davat bacha na veskere php soubory co se sem tam prepisuji a po prepisu je invalidovat a nebo mit obecne zaplou kontrolu last modification time
Na vše toto se hodí memcahe(d)
Do memcached si to pole jednoduše uložíš také, pod nějakým klíčem.
Následně daný záznam invaliduješ pomocí toho klíče v případě editace
stromu. Není problém si tam serializovat klidně celé objekty (tam už
záleží na velikosti vyhrazené RAM pro memcached a na mnonžství cachovaným
objektů).
Opcache si můžeš nastavit tak či tak, ale pro tyto účely se hodí přímo
nějaké storage (file/memcahce/memcached/redis...).
Btw. něco podobného jako je tvůj návrh s uloženou path (u mne ve
formátu 1:2:3
) používám pro vyhledávání v ElasticSearch, kde
běžné asociace neexistují. V tomto "sloupci" pak hledám pomocí regexu
záznamy, které potřebuji.
Zobrazeno 15 zpráv z 15.