Látogatotság gyors tételes keresése
Sziasztok!
Van egy táblám amibe azt tárolom, hogy egy oldalon mikor melyik felhasználó melyik másik felhasználó adatlapját nézte meg:
TÁBLA struktúrája:
mikor (mikor történ a látogatás)
to_user (annak a felhasználónak az egyéni azonosítója akiknek az adatlapját megnézték)
from_user (annak a felhasználónak az egyéni azonosítója aki nézte az adatlapot)
A problémám, hogy ez a tábla így villám gyorsan több milliósra fel fog duzzadni.
Attól tartok, hogy az indexelés ellenére egy gyenge pontja lesz a rendszernek.
Főleg akkor amikor ebből a táblából részletes adatokat kell kivennem.
Hogyan lehetne optimalizálni?
Sajnos mivel tételes adatokat kell kiszednem, így azt az utat nem találtam járhatónak, hogy mondjuk naponta csinálok egy összesítő táblát, mivel nem arra vagyok kíváncsi, hogy mondjuk a múlt hónapban (, vagy múlt héten, vagy esetleg a kezdetektől) hányan nézték meg az adatlapját egy felhasználónak, hanem konkrétan ki voltak azok.
Egyenlőre ilyesmiben gondolkodok hangosan:
A felhasználókat mondjuk 1000-es csoportokra bontom (to_user szerint) és 1000 felhasználóként külön táblában gyűjteném az adatokat.
Így az írás is gyorsabb lenne (mert tudom a megnyitott adatlap tulajdonosa melyik 1000-es csoportba esik), illetve az olvasás is, mert amikor az ügyfél meg szeretné nézni, hogy kik nézték az adatlapját akkor is az adatokat néző ügyfélhez tartozó adattáblából kell csak kikeresni az adatokat.
A fenti kialakításnál biztosan van jobb megoldás is, mivel több ponton máris sántít a dolog, mert sajnos fordítva is kell tudnom keresni a táblában.
A felhasználók ugyanis arra is kíváncsiak lehetnek, hogy egy adott időintervallumban mely felhasználók adatlapjait nézte már meg. A fenti struktúra sajnos erre már egyáltalán nem ad megoldást, mivel ebben az esetben végig kellene olvasnom az össze létrehozott táblát.
Ha fokozni szeretném, akkor még ott van az az eset amikor arra kíváncsiak az ügyfelek, hogy kik azok a felhasználók akik nézték az ő adatlapjukat, viszont ők még nem nézték meg a másikét.
Van valami jó ötletetek arra, hogy hogyan lehetne valamilyen módszerrel úgy megoldani a tárolást, hogy ne lassuljon be hosszú távon is ettől a rendszer?
MYSQL 5.0 adott most hozzá.
Előre is köszi.
Zoli
■ Van egy táblám amibe azt tárolom, hogy egy oldalon mikor melyik felhasználó melyik másik felhasználó adatlapját nézte meg:
TÁBLA struktúrája:
mikor (mikor történ a látogatás)
to_user (annak a felhasználónak az egyéni azonosítója akiknek az adatlapját megnézték)
from_user (annak a felhasználónak az egyéni azonosítója aki nézte az adatlapot)
A problémám, hogy ez a tábla így villám gyorsan több milliósra fel fog duzzadni.
Attól tartok, hogy az indexelés ellenére egy gyenge pontja lesz a rendszernek.
Főleg akkor amikor ebből a táblából részletes adatokat kell kivennem.
Hogyan lehetne optimalizálni?
Sajnos mivel tételes adatokat kell kiszednem, így azt az utat nem találtam járhatónak, hogy mondjuk naponta csinálok egy összesítő táblát, mivel nem arra vagyok kíváncsi, hogy mondjuk a múlt hónapban (, vagy múlt héten, vagy esetleg a kezdetektől) hányan nézték meg az adatlapját egy felhasználónak, hanem konkrétan ki voltak azok.
Egyenlőre ilyesmiben gondolkodok hangosan:
A felhasználókat mondjuk 1000-es csoportokra bontom (to_user szerint) és 1000 felhasználóként külön táblában gyűjteném az adatokat.
Így az írás is gyorsabb lenne (mert tudom a megnyitott adatlap tulajdonosa melyik 1000-es csoportba esik), illetve az olvasás is, mert amikor az ügyfél meg szeretné nézni, hogy kik nézték az adatlapját akkor is az adatokat néző ügyfélhez tartozó adattáblából kell csak kikeresni az adatokat.
A fenti kialakításnál biztosan van jobb megoldás is, mivel több ponton máris sántít a dolog, mert sajnos fordítva is kell tudnom keresni a táblában.
A felhasználók ugyanis arra is kíváncsiak lehetnek, hogy egy adott időintervallumban mely felhasználók adatlapjait nézte már meg. A fenti struktúra sajnos erre már egyáltalán nem ad megoldást, mivel ebben az esetben végig kellene olvasnom az össze létrehozott táblát.
Ha fokozni szeretném, akkor még ott van az az eset amikor arra kíváncsiak az ügyfelek, hogy kik azok a felhasználók akik nézték az ő adatlapjukat, viszont ők még nem nézték meg a másikét.
Van valami jó ötletetek arra, hogy hogyan lehetne valamilyen módszerrel úgy megoldani a tárolást, hogy ne lassuljon be hosszú távon is ettől a rendszer?
MYSQL 5.0 adott most hozzá.
Előre is köszi.
Zoli
nem kell félni
ha minden jól megy, mondjuk egy év alatt 30 millió sor kerül a táblába. ennyit képes gyorsan kezelni szerintem a MYSQL, szóval emiatt nem kell aggódni. Ha mégis szét akarod bontani több táblára (ami a kétirányú keresést nehezíti), akkor sem 1000 sorra kellene, hanem kb 5 milliósra. ezer sor az olyan kevés mint ha nem is létezne :)
amúgy MyISAM-mos táblába 2^32 sor fér (kb. 4miliárd)
InnoDB-ben nem tudom milyen korlát van, de mondenkép jobb. A manual megemlít egy portált, ahol 2 terrát tárolnak ilyen rendszerben, 800 insert/update per másodperc terheltséggel.
ütős
Nem soronként
Köszi a gyors választ.
Az 1000-es szétosztást nem soronként hanem felhasználónként értettem.
Tehát az első táblába az 1-999-is azonosítójú felhasználók adatai kerülnének.
Ha egy ember mondjuk átlagosan naponta 20-30 adatlapot néz meg, akkor az 7.300.000-10.950.000 rekordot jelent egy évben 1000 felhasználónként.
Egy régi rendszer lenne kibővítve amiben most is már 30.000 felett vannak a felhasználók. Ezért keresek jó megoldást, mert az egy táblára nézve évente 219.000.000-328.500.000 rekordot jelentene akár.
És akkor még csak 1 évig lehet visszakeresni.
Néztem, hogy az 5.1-ben van egy lehetődés az adattáblák osztására
partitioning, de nekem csak mysql 5.0 adott.
Sőt tavaly év végén még nagy cikkezések voltak, hogy sok hiba van az 5.1-es verzióban.
Ezen kívül azt sem tudom partition mennyire stabil, mert még úgy nézem nagyon új dolog.
Tehát ha van valakinek valami jó ötlete, akkor azt nem titkolja...
;)
Köszi.
Zoli
nem lenne elég ha..
-ki
-kit
-legutoljára mikor
-összesen hányszor
Nézett meg? Mert így csökkenne a rekordok száma.
üdv,
Balázs
Visszamenőleg is...
Köszi a választ.
Sajnos visszamenőleg is szükség van az adatokra.
Tehát nem csak az utolsó látogatás számít.
Én azzal próbálom csökkenteni az adatokat, hogy ha az egyik ügyfél megnézte egy másik ügyfél adatlapját, akkor ezt a tényt rögzítem a session-ban, és amíg él a session addig újra nem rakom le a látogatás tényét újra az adattáblában.
Viszont ha másnap is megnézi ugyanaz a felhasználó ugyanannak a másiknak az adatlapját, akkor azt újra el kell tárolnom, mivel valósan vissza kell tudnom követni ki mikor nézte az adatlapokat.
Ez a bajom.
Újabb ötlet?
Üdv:
Zoli
Union
arra gondoltal mar, hogy havi szinten bontsd le az adatokat? Union / Union All (SQL) segitsegevel konnyen skalazhatova is valik a visszakereses.
-cs-
Sanyi
Igen
Igen gondoltam az idő alapján történő bontásra is.
Viszont ennél két kérdés merül fel bennem:
- Ha mondjuk UNION segítségével 8-10 táblát kell összekötnöm, akkor maga az alap SELECT-et 8-10x kell beírnom. Nincs olyan megadás hogy a SELECT-et csak egyszer kellene megadni és utána csak a kíván táblákat?
- Ha a kölcsönös látogatás kell figyelni (pl. az egyik ügyfél kíváncsi arra, hogy kik azok az ügyfelek akik az elmúlt 3 hónapban megnézték az adatlapját és ő még soha nem néztem meg az övékét (vagy mondjuk 1 évre visszamenőleg)), akkor az összes táblát mégis végig kell olvasni.
Amúgy pont ugyanez a problémám az ügyfelek szerinti bontásban is.
Ott is ha csak arra vagyok kíváncsi, hogy kik nézték egy adott ügyfél oldalát és mikor akkor mindig egy táblát kellene olvasnom. Ha viszont a kölcsönösséget is kell, akkor szintén fel kell olvasnom az összes résztáblát, mivel tuti mindegyikben lenne 1-2 visszaellenőrizendő adat.
Zoli
Handos gondolkodás
Ugye ha az eredeti 1000 ügyfelenkénti szétbontáshoz visszanyúlok, akkor az arra jó, hogy az ügyfél gyorsan vissza tudja nézni mikor kik nézték az adatlapját, de arra nem, hogy ő kiket nézett meg, illetve a kölcsönösség vizsgálatára sem.
Ha azt szeretném vizsgálni, hogy az adott user kiket nézett meg, akkor pont egy fordított táblára lenne szükség ahol szintén 1000 ügyfelenként azt indexelném le, hogy kit nézett megy adott ügyfél és nem azt, hogy kik nézték meg az ügyfelet.
Ha lenne két ilyen táblám, akkor egy szimpla JOIN segítségével mindig csak 1-1 táblarészt kellene összekapcsolnom.
Pl.:
Ha az ügyfél azonosítója 2134, akkor a ki_nezett_2 táblát a kit_neztem_2 táblával kell csak összekapcsolnom.
A hátránya az egésznek csak annyi, hogy minden adat kétszer van letárolva.
Egyszer a ki_nezett_x egyszer kit_neztem_x táblában.
Tehát ez sem ideális.
Zoli
es ez problema
Ha ugyes logikaval nevezed el a tablakat pl. tabla_012008,tabla_022008 akkor szekvencialisan konnyeden ossze tudod allitani a selecteket az erintett idointervallumra. A where feltetelre is igaz mindez.
- ne haragudj, de mindig is vegig kell nyalazni a tablakat, hacsak nem csinalsz minden honap vegen egy indextablat a kapcsolatoknak es azt kerdezed le, mig az aktualis honap meretenel fogva normalisan is le tudod kerdezni. Persze kerdes mekkora idokozoket kell kialakitanod. Te hatarozod meg, vagy az ugyfel teljesen szabadon adhatja meg az idopontot.
- ha indextablakat keszitesz, abban mar osszesitett adatok fognak szerepelni, ugye ami nagyban csokkenti a sorok szamat es a lekerdezes sebesseget. Ha te hatarozod meg a visszakeresheto idointervallumokat, akkor annak megfelelo indextablakat kell kesziteni. 1 het, 1 honap, negyedev, felev, ev stb.
-cs-
Sanyi
Válasz
Ezzel nem is volt problémám. Ez teljesen logikus így.
Elméletileg úgy kell most megcsinálnom, hogy minden szabadon állítható legyen.
"ne haragudj, de mindig is vegig kell nyalazni a tablakat"
Igen. Pont ez a problémám. Ezt szeretném elkerülni mindamellett, hogy részletes adatokra van szükségem és nem csak összesítésekre.
Ha pl. az kellene, hogy kik néztek az elmúlt két hétben, vagy az, hogy kit néztem én, akkor csak kiválasztom azt az 1-2 táblát amiben az elmúlt 2 hét adatai vannak, és ezzel el van intézve a dolog.
Még akkor sincs gond, ha egy hasonló kis intervallumban kell a kölcsönösséget is figyelni.
A probléma ott kezdődik, ha nagy intervallumok vannak egyik vagy másik oldalon. Pl.: az kellene, hogy kik néztek az elmúlt két hétben, de azok közül is csak azok, akiket még soha az életben nem láttam (pl. 3 év). Vagy visszamenőlegesen a kezdetekig kinek az adatlapjait néztem.
Ezekben az esetekben végig kell olvasnom az összes résztáblát.
Mondtad az összesítő táblát. Sajnos mivel nincsenek előre definiált tartományok, ezért nehéz meghatározni mi legyen a bontás alapja.
Úgy érzem, akkor tudna egy ilyen hatékonyan működni, ha előre le tudnám fektetni az időtartományok alapjait.
Pl. minden nap legenerálom a heti, havi, féléves, teljes tartományt és akkor ezekben a tartományokban lehet könnyen kölcsönösséget vizsgálni.
Sajnos az én esetemben ha azt szeretné az illető, hogy 2008.11.13-2009.02.03-ig kíváncsi az adatokra, akkor ezekkel az összesítő táblákkal csak előre megjósolni futom, hogy lehet, hogy az adott illető beleesett e a vizsgált intervallumba vagy sem, viszont pontosat csak a nagy tábla végigolvasása után tudok majd.
Ezért gondolkodta inkább az ügyfél szerinti bontásban, mert ott maga az ügyfél egy olyan érték, ami konstans, az nem változhat egy-egy lekérdezés közben, míg az idő igen.
visszaterve
- kik neztek meg az adott felhasznalo adatlapjat
- egy adott felhasznalo kinek az adatlapjat nezte meg
egy adott honapban.
Gyakorlatilag mivel ezeket nem kell ujrageneralni, hanem csak minden honap(esetleg het) vegen, ezert barmikor ujra felhasznalhatod oket. Ha valaki nem egesz honapot kerdez le, akkor ott a teljes honapokat az osszesito tablakbol veszed, mig a nem teljes honapokat rendesen lekerdezed.
Egy masik megoldas, hogy xml-be kiirod oket es xsl meg is tudod formazni az osszesito havi tablakat felhasznalonkent, ezzel nem terheled az adatbazisszervert es gyakorlailag ha meg1 szervert beallitasz akkor terheleselosztast is segiti ez a megoldas.
-cs-
sanyi
UI.: mindenesetre en helyedben kiprobalnam ezt mintaadatokkal (generalt adatokkal)