Optimalizacia dotazov do db

Programovacie jazyky, rady, poradňa...
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

Mam taku vseobecne - konkretnu otazku: Ak mam napr. temy s prispevkami, a chcem zobrazovat, kolko je v nich prispevkov, je lepsie napisat kod tak, aby sa pri nacitani zoznamu tem pocital, kolko prispevkov je v kazdej teme cez COUNT * alebo spravit tabulku pre temy, kde bude stlpec pocet_prispevkov a hodnota sa bude menit cez prikaz UPDATE pri kazdom novom prispevku v danej teme.

Tieto dve moznosti ma napadaju pri vsetkom, co si vyzaduje zobrazovat nejake suhrnne informacie, no neviem, co je rozumnejsie, kedze este nemam realne skusenosti z praxe.
Ovecka
Darca
Darca
Používateľov profilový obrázok
Príspevky: 1227
Registrovaný: 25 aug 2005, 0:57

Re: Optimalizacia dotazov do db

Príspevok od používateľa Ovecka »

jednoducho cez mysql_num_rows ak poznas
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa audiotrack »

mysql_num_rows nerieši jeho problém, to si napísal úplne od veci
K téme: musíš si dobre premyslieť čo sa ti viac oplatí. Vedenie si počtov ako hodnotu je efektívnejšie ak ide o obrovské tabuľky, no na druhú stranu musíš updatovať aj pri pridaní a zmazaní príspevkov.
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

To spatne znizovanie poctu pri mazani nie je problemom, staci si dat pozor pri zostavovani. Mne sa viac pozdava urobit pre vsetko taketo pocitadla a upravovat v nich pri zapisoch pocty, prikazy SELECT tak budu jednoduchsie a rychlejsie, no bojim sa, ze to takymto sposobom pretazim na strane zapisu.

Pre obraz uvadzam kod, ktory momentalne sluzi na zobrazenie zoznamu tem v danom fore, ktory pochadza z literatury, z ktorej cerpam. Mne sa to vsak zda prilis zbytocne zlozite a prekombinovane. Takto sa pri kazdom nacitani fora vytvori jedna docasna tabulka, nalozi sa identifikatormi tem a datumami poslednych prispevkov z tabulky prispevkov a pomocou nej sa generuje zoznam tem. Bojim sa, ze taketo riesenie bude pri vyssej zatazi pomale a problematicke. Preto by som radsej urobil jednu tabulku pre temy, kde by som skladoval udaje potrebne pre generovanie takehoto zoznamu a odtial ich cital jednoduchym selectom doplnenym o strankovanie.

Dalsi takyto pripad je uzivatelsky profil. Tam by som chcel pre jednotlivych uzivatelov zobrazovat v ramci ich ativity na stranke pocet prispevkov, clankov, komentarov, fotogalerii a pod. A otazka je, ci na jednej takejto stranke pouzit 10 dotazov s prikazom COUNT pre rozne tabulky, ale jeden SELECT pre tabulku pocitadiel, ktora by sa priebezne updatovala.

Kód: Vybrať všetko

$sql = 'CREATE TEMPORARY TABLE tmp (
            tema_id INTEGER UNSIGNED NOT NULL DEFAULT 0,
            postdate DATETIME NOT NULL
        )';
mysql_query($sql, $db) or die(mysql_error($db));

$sql = 'LOCK TABLES uzivatel_info READ, frm_prispevky READ';
mysql_query($sql, $db) or die(mysql_error($db));

$sql = 'INSERT INTO tmp SELECT
            tema_id, MAX(datum_odoslania)
        FROM
            frm_prispevky
        WHERE
            forum_id = ' . $forumid . ' AND tema_id > 0
        GROUP BY
            tema_id';
mysql_query($sql, $db) or die(mysql_error($db));

$sql = 'UNLOCK TABLES';
mysql_query($sql, $db) or die(mysql_error($db));

$sql = 'SELECT SQL_CALC_FOUND_ROWS
            t.id as tema_id, t.predmet as t_subject, CONCAT_WS(" ",u.titul,u.krstne_meno,u.priezvisko) as t_author,
            COUNT(p.id) as numreplies, t.datum_odoslania as t_posted,
            tmp.postdate as re_posted
        FROM
            uzivatel_info u JOIN frm_prispevky t ON t.user_id = u.user_id
            LEFT JOIN tmp ON t.id = tmp.tema_id
            LEFT JOIN frm_prispevky p ON p.tema_id = t.id
        WHERE
            t.forum_id = ' . $forumid . ' AND t.tema_id = 0
        GROUP BY
            t.id
        ORDER BY
            re_posted DESC
        LIMIT ' . $start . ', ' . $limit;
$result = mysql_query($sql, $db) or die(mysql_error($db));
ropman
Medium Professional
Medium Professional
Príspevky: 1250
Registrovaný: 12 apr 2010, 21:07

Re: Optimalizacia dotazov do db

Príspevok od používateľa ropman »

jednoznacne to riesit updatovanim stlpca - rozdiel v rychlosti je nezrovnatelny. mozes si na to napisat aj triggre aby si to nemusel riesit v aplikacii.
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

Tabulky som teda prerobil. Slabe miesto moze byt teraz to updatovanie. Vlozenim prispevku sa teraz updatuju dve dalsie tabulky, ak pocas toho nastane vypadok, ale nejaky iny problem, moze sa to rozsynchronizovat a pocitadla budu ukazovat zle hodnoty.

Preto asi este napisem nejake skripty na synchronizaciu, ktore by som spustal cez cron v noci, tak by to malo byt dostatocne osetrene. Snad
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa audiotrack »

ak tam nemáš podmienky či sa skutočne to query vykonalo správne, tak áno, môže sa to rozsynchronizovať. To je ale chyba tvojho kodu že píšeš lahostajne, a nie zlého návrhu
ropman
Medium Professional
Medium Professional
Príspevky: 1250
Registrovaný: 12 apr 2010, 21:07

Re: Optimalizacia dotazov do db

Príspevok od používateľa ropman »

tak to by stacilo dat do transakcie
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

Tabulky su vsetky MyISAM, na Innodb nechcem prejst kvoli fulltextovym indexom.

audiotrack: Ako osetrit kod na vypadok databazy?Ak sa napriklad vykona prvy prikaz, potom sa vypne server, updaty uz neprebehnu, tak tam asi nepomoze ziadna podmienka, ale pravidelna kontrola, ci dane sucty sedia, ci sa mylim?
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa audiotrack »

ropman ti dal odpoveď. Hodíš to do transakcie, a podmienka či sa vykonala alebo nie (transakcia je atomická, čiže sa vykona celá alebo vôbec). Ak ideš ale do takýchto extrémov ako vypnutie serveru, tak ti pomôže iba extrémne riešenie ako si to zakaždým kontrolovať v nejakom trigerri a to už je zase proti optimalizácii :)
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

No ale transakcie predsa pri MyISAM nie su nie? A ako som pisal, MyISAM povazujem za lepsiu volbu
beluský
Darca
Darca
Používateľov profilový obrázok
Príspevky: 317
Registrovaný: 21 sep 2006, 13:46

Re: Optimalizacia dotazov do db

Príspevok od používateľa beluský »

v com je vlastne najdolezitejsi rozdiel medzi myisam a innobDb a tie ostatne?
je to hlavne toto?? alebo nejake skusenosti tvdia aj nieco viac...
Prílohy
db.png
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

Mam pred sebou jednu ulohu. V jednej tabulke je zoznam poloziek. V druhej tabulke je zoznam dokumentov, ktore patria k jednotlivym polozkam. Jedna polozka ma minimalne jeden suvisiaci dokument, ale moze ich mat aj viac. Polozky zobrazujem v tabulke, kde je posledny stlpec urceny pre suvisiace dokumenty. Tam, kde je dokumentov viac, urobi sa do jednej bunky zoznam dokumentov. Na stranku zobrazujem 50 poloziek.

Ako to riesit v php a mysql? Ak by bolo ku kazdej polozke po 1 dokumente, stacil by jeden SELECT. Ale predpokladam, ze ked moze byt tych dokumentov viac, asi to take lahke nebude.

Napadaju ma dve riesenia: spravit pre kazdy riadok jeden SELECT z tabulky dokumentov, co bude 50 queries navyse, alebo jeden SELECT z tabuky dokumentov na zaciatku skriptu a pre kazdy riadok tabulky ho prebehnut cyklom a vybrat suvisiace dokumenty.

Alebo mam obmedzene poznatky a ide to ovela jednoduchsie a elegantnejsie a prave preto pto pisem sem.

Vdaka za rady
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa audiotrack »

select * from polozky left join dokumenty on dokumenty.id_polozky = polozky.id_polozky
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

Takymto sposobom mi to spravi v tabulke dva riadky, kde bude jedna polozka akurat v poslednom stlpci budu rozdielne dokumenty. Ja to chcem mat na jednom riadku a v bunke posledneho stlpca dva udaje
Prílohy
priklad.png
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa audiotrack »

to si už vypíš v php. Klasika while($row = mysql_fetch_array($result)) if($row["id"] == $predosle_id) //vypis do rovnakej bunky;
else //uzavri bunku, otvor novy riadok a vypis vsetko. Nezabudni na $predosle_id = $row["id"]
Holubar
Darca
Darca
Používateľov profilový obrázok
Príspevky: 3894
Registrovaný: 24 feb 2005, 21:26
Bydlisko: Senec
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa Holubar »

Tak to je presne to elegantne riesenie, na ktore som sam neprisiel. Trvalo mi sice par hodin, kym som to rozbehal, ale zase sa na tie cykly pozeram trochu inak. Vdaka za radu.

//autoeditácia príspevku (18 Apr 2011, 0:17)
Mam dalsiu otazku: Ked mam jednu tabulku s clankami a dalsiu s obrazkami k clankom, nastava situacia, ze k jednemu clanku moze byt napr 30 obrazkov.

Ked to vyberiem jednym selectom pomocou JOIN, vrati mi 30 riadkov - a v kazdom bude aj text toho clanku. Ako to funguje v takom pripade? Nebude sa prenasat prilis velke mnozstvo dat, ak bude text clanku dlhsi? Nebude lepsie spravit jeden extra select na zaznamy o obrazkov k danemu clanku?
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: Optimalizacia dotazov do db

Príspevok od používateľa audiotrack »

na to sa nedá jednoznačne odpovedať. Ale jedno aj druhé riešenie sa bude isto líšiť iba o zlomky mikrosekúnd (ak je tých riadkov iba 30 a nie stotisíce) takže osobne by som to vôbec neprepočítaval a dal by som proste druhý select. Už len pre jednoduchosť a prehľadnosť v kode
Napísať odpoveď