Autor Zpráva
H13
Profil
Ahoj řeším následující problém a napadají mě dvě varianty řešení. Jde o hlasování, např. známky 1 až 5. Zajímalo by mě jakým způsobem ukladát výsledky a jakým způsobem je zobrazovat, která varianta je pro server optimální:

a) Uživatel např. vybere známku 3 a ta se uloží do databáze společně s jeho daty (tak aby nemohl hlasovat znovu), např.:

tabulka_hlasovani
id uživatele, id sekce hlasování, znamka ... a protože takových záznamů může být tisíce, napadlo mě, že když se průměrná známka bude většinou jen ukazovat, pak se vloží průměrná známka s počtem hlasujích od samostatné tabulky:
tabulka_hlasovani_zobrazeni, kde bude jen:
id_sekce, prumerna_znamka, pocet_hlasujicich... KDYŽ SE TEDY BUDE ZOBRAZOVAT PRŮMĚRNÁ ZNÁMKA A POČET HLASUJÍCÍCH NA STRÁNCE, pak bude stačit jednoduše vybrat tyto hodnoty.... nevýhody mohou být v tom, že když se přidává hlasování, nebo se bude měnit, nebo se bude mazat, pak se vše musí přepočítávat...

b) To samé co za a), jenom nebude existovat tabulka_hlasovani_zobrazeni a pro každého návštěvníka se bude muset provést dotaz ve všech záznamech hlasování a to COUNT a AVG

Zajímalo by mě, k jaké variantě by jste se přiklonili... zda zvolit přepočítávání výsledků a vkládání zpět do tabulky po každém zadání, mazání, měnění při malém počtu takových operací oproti operaci zobrazování (zobrazování a select AVG a COUNT z tabulky tabulka_hlasovani), kdy zobrazování je mnohem častější

No doufám, že je to k porozumění... v podstatě jde o to zda SELECT COUNT a AVG z tabulky s mnoho řádky bude velkej záběr oproti zobrazování těchto informací z jednoho řádku...

Díky za názory...

Honza
bukaj
Profil
H13
Druhou tabulku bych nevytvářel. V podstatě by to byla akorát cache počítaná z výsledků v té první. A na cachování jsou zde myslím rychlejší metody než databáze.
H13
Profil
bukaj
bohužel cachování do toho asi nezatáhnu protože mu moc nerozumím

s tou druhou tabulkou jsem to myslel tak, že např.

zobrazení známky a počtu hodnocení bude např. 1000 x a oproti tomu bude akce hlasování třeba 10 x v nějaký časový jednotce ... takže i kdyby to 10 x mělo 'cachovat', zda to bude mít cenu:

x tisíckrát použití COUNT A AVG z mnoha záznamů OPROTI
x tisícktrát puužití SELECT prumerna_znamka, pocet_hlasujicich
bukaj
Profil
H13
bohužel cachování do toho asi nezatáhnu protože mu moc nerozumím
Řekl bych, že v takovém Zendu je to hezky uděůané i popsané. Třeba se inspiruješ :o)

s tou druhou tabulkou jsem to myslel tak, že např. ...
Neboj, to jsem, doufám, pochopil ;o) Pouze jsem chtěl říct, že cachovat výsledky v databázi, ze které je taháš, asi nebude to pravé ořechové. Samozřejmě, že by vybírání jen jednoho řádku z databáze měla být mnohem menší časová zátěž než neustále počítání průměrů hodnot z mnoha řádků a jejich počty. Mně osobně by prostě vadilo, kdybych se při přidávání ještě musel starat o nějaké další dopočítávání. Dalo by se to, myslím, vyřešit pomocí triggerů, ale to cachování přímo v aplikaci mi přijde rychlejší a nejspíš i jednodušší.
joe
Profil
Po mých (ne)zkušenostech :) bych to udělal takhle:

Protože je mnohem lepší si ukládat součet hlasů a nebo rovnou už průměr než to pokaždé pomocí COUNT vybírat, tak bych zapisoval jen ten součet / průměr (co chceš) do té tabulky kde ty hlasy chceš mít.
Abys pochopil jak to myslím: máš třeba nějaké příspěvky, tak to rovnou budeš ukládat do tabulky s příspěvky do příslušného sloupce.
Pak uděláš další tabulku, nějakou temp_hlasovani třeba a tam budeš ukládat kdo hlasoval. Pokud chceš znemožnit aby hlasoval jen jednou tak ho tam záznam necháš, já bych udělal, že třeba za týden může hlasovat znovu, takže bych všechny řádky z téhle tabulky smazal, co byly starší než 1 týden. Snad jsi to pochopil a k něčemu ti to bude... ;-) Nemusíš nic cachovat, je to jednoduché a efektní (doufám).
Do té pomyslné tabulky s příspěvky, bych osobně ukládal kolik lidí hlasovalo a celkový součet hlasů - pak bych už vybíral jen tyto dva sloupce a vydělil.
H13
Profil
joe
no tak jsem to taky myslel s tou druhou tabulkou, že bych do ni ukládal pouze 'kolik lidí' a 'průměr'

To znamená, člověk zadá hlas, např. známku 5....při jeho zadání se uloží záznam do tabulky HLASOVANI (zde se bude hlídat jestli už hlasoval) a teď zase nové dvě možnosti:

1. Jednoduše po zadání hlasování do HLASOVANI vyberu COUNT a AVG a vložím do tabulky např. COUNT_AVG_HLASOVANI:

-- ušetřím různé přepočítávání, jako že bych prvně vytáhl z COUNT_AVG_HLASOVANI starou hodnotu a přepočítal a vložil zpět (při jakékoliv akci: Vkládání od uživatele, mazání od administrátora, publikování a nepublikování)
-- ušetřím dotaz COUNT a AVG v případě, že se hlasování bude pouze zobrazovat (nejčastější případ)

2. Místo toho aby se konkrétní hlas uložil pouze do HLASOVANI, pak se připočte i do COUNT_AVG_HLASOVANI ... což oproti 1. možnosti bude složitější, protože se to bude muset při každé změně přepočítávat, zatímco u první se pouze veme COUNT a AVG a ta se

Možná je to lepší takto ve zkratce:

1. MOŽNOST:
--- INSERT DO hlasovani
--- SELECT COUNT, AVG z hlasovani
--- UPDATE count_avg_hlasovani novou hodnotou

2. MOŽNOST:
--- INSERT DO hlasovaní
--- SELECT count a avg z count_avg_hlasovani a pomoci php přepočítat nové výsledky
--- UPDATE count_avg_hlasovani novou hodnotou

U obou možnost se to bude provádět pouze při zadání hlasování
Vytahování výsledků bude prováděno z jednoho řádku

3. MOŽNOST (bez 'cachovací' tabulky count_avg_hlasovani)
--- INSERT DO hlasovani
U této možnosti se to bude provádět při zadávání hlasování, ALE
vytahování výsledků (nejčastější akce) bude prováděna i s hledáním COUNT a AVG...

U první možnost při akci mazání smažu záznam z HLASOVANI, odeberu 1 z COUNT a přepočtu AVG (bude to složitější, protože si budu muset vyjet starou známku)
Zatímco u druhé možnosti při akci mazázní smažu záznam z HLASOVANI a nebudu muset nic provádět, protože COUNT a AVG se mi uděla nová hodnota ze SELECTU count a avg z HLASOVANI....

takže mě asi příjde nejlepší ta 2 MOŽNOST (samozřejmě v případě neprovedení cachování :-) )

Honza
joe
Profil
Uff, myslel jsem to uplně jinak, to co děláš je podle mě úplně zbytečné. Přečti si co jsem napsal ještě jednou a když to nebude k pochopení, tak napiš, vysvětlím to lépe :-)
H13
Profil
joe
Stále nechápu jaký je v tom rozdíl...

u tebe jsou dvě tabulky a u mě taky:

- tabulka pro AVG a COUNT (u mě COUNT_AVG_HLASOVANI, u tebe hlavní tabulka
- tabulka pro záznam o hlasujících (u mě HLASOVANI, u tebe dočasná (temp_hlasovani)

Do HLASOVANI ukladam informace o hlasujicim
do COUNT_AVG_HLASOVANI updatuju pouze průměr a počet (teď neberu v úvahu další složitější věci, jako id sekce, atd...)

no a vyjmenoval jsem různý možnosti aktualizace tabulky COUNT_AVG_HLASOVANI (1. z tabulky HLASOVANI,2. z aktuálního hlasování,3. žádná tabulka)

Jestli můžeš, tak mi prosím vysvětli, třeba jen rozdíl, díky. Honza
joe
Profil
Teď když to tak pročítám, možná to myslíš stejně, ale zdá se mi tam ten jeden dotaz zbytečně. Vysvětlím to na nějakém konkrétním příkladu.

Problém: Máme fotky, každá z nich může být hodnocena známkou 1 - 5 pouze jednou od registrovaných uživatelů.
Řešení: Budou dvě tabulky, fotky a hodnoceni_temp
Tabulka fotky:
id | popis | soubor | .... | soucet_hlasu | celkem_hodnotilo

Tabulka hodnoceni_temp:
uzivatel_id | fotka_id | hlas | datum

---

Tím jsou vyřešené tabulky.
A teď, když bude někdo hlasovat, zkontroluješ, jestli už v tabulce hodnoceni_temp neni, když ne, tak do tabulky hodnoceni_temp se vloží kdo hlasoval, id fotky které patří hlas, samotný hlas (1-5) a čas, kdy to bylo.


A v tabulce fotky, jen updatujes radek:

update fotky set soucet_hlasu = soucet_hlasu + {$_GET['hlas']}, celkem_hodnotilo = celkem_hodnotilo + 1 where id = {$_GET['fotkaId']} limit 1

---

Možná jsi to takhle myslel a já to jen nepochopil ;-)
H13
Profil
Jo takto jsem to myslel jako MOŽNOST 2 (trochu jsem to myslím spletl s tím že mě vyhovuje MOŽNOST 2, myslel jsem MOŽNOST 1)

OK tak si rozumíme, co ale v případě, že administrátor
SMAŽE HLASOVÁNÍ
- pak při tomto systému pomocí updatu odečteš 1 hlas a přepočteš průměr hlasování
NEBO UDĚLÁ HLASOVÁNÍ NEPUBLIKOVANÝM (publish, unpublish)
- pak přit tomto systému zase odečteš jeden hlas a pomocí selectu zjistíš kolik měl bodů a zase přeměníš průměr... to znamená, že zde bude hodně dotazů...

Zatímco, kdybych po každé změně využil SELECT AVG nebo COUNT z tvé tabulky hodnoceni_temp, pak bych nemusel nic přepočítávat, Př:


- Uživatel zadá hlasování (hlas se zadá do hodnoceni_temp, z hodnoceni_temp se vybere průměr a počet (AVG a COUNT) a uloží se do tabulky fotky
- Administrátor zruší hlasování (hlas se vymaže v hodnoceni_temp, z hodnoceni_temp se vybere průměr a počet (AVG a COUNT) a uloží se do tabulky fotky
- Administrátor 'znepublikuje' hlasování (nastaví se public = 0 hodnoceni_temp, z hodnoceni_temp se vybere průměr a počet (AVG a COUNT) samozřejmě s podmínku WHERE public = 1 a uloží se do tabulky fotky (ta podmínka se samozřejmě používá všude)

Tím pádem (třeba delete) za a)

- SELECT průměr a počet hlasů z tabulky fotky
- SELECT známku z tabulky hodnoceni_temp
- odečtení známky a vypočtení nového průměru, odečtení 1 z počtu
- INSERT do tabulky fotky (nový průměr, nový počet)
- DELETE do tabulky hodnocení_temp

za b)
- DELETE do tabulky hodnoceni_temp
- SELECT z tabulky hodnoceni_temp (avg a počet)
- INSERT do tabulky fotky (nové hodnoty)

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: