Üzenetkezelő rendszer
Sziasztok!
Most olvastam a hasonló témát, én is ilyesmivel ügyködök és a véleményetekre, tapasztalatotokra lennék kíváncsi.
Szóval a cél egy oldalon belüli üzenetkezelő rendszer, php + mysql.
Amit tudnia kell a rendszernek:
Lényegében, van 3 csoport user - kliens - admin. User azoktól a kliensektől kapja meg az üzeneteket, akiket követ. ( + admin, de ő természetesen nincs feltételhez kötve, minden usernek küldhet )
User és kliens között N:M kapcsolat van.
Az én elképzelésem, ameddig jutottam:
1. Ábrázoltam a kapcsolatokat külön ( nem csak a levelezés miatt kell )
kapcsolatok tábla: user_id - kliens_id
2. Van egy táblám az üzeneteknek:
msg_id, sender_id, subject stb
Na most user megkapja a "kapcsolata" alapján a kért leveleket, ez idáig stimmel.
Szeretnék állapotot is tudni a levelekről pl olvasott -> új üzenet érkezést jelezni, vagy törölt -> a user törölhesse a levelet a "saját listájáról".
Ehhez azt gondolom kell készítenem még egy táblát:
3. üzenetek_állapota tábla:
user_id, msg_id, status ( olvasott/törölt )
Akkor születne rekord, ha a user megnyitotta a levelet. ( ?? )
Na itt kezd kicsit sántítani a dolog nekem... Vélemény?
Ekkor, az "új üzenet érkezett" funkciót, ( képzeljük el ezt most fb -sen, piros boríték stb, nem ez a cél csak valami hasonló, lényeg hogy valahogy szeretném majd használni ), megkapnám a két tábla különbségeként, illetve listázáskor a törölteket levonva. DE ez a kezelés nekem elég macerásnak tűnik...
Kicsit utána számolva, ( ez nem egy éles project, de feltételezve igazi működést ) mondjuk 5000 user nél és 500 kliens nél, ha átlagosan 1 kliens havi 3 üzenetet küld és 1 user átlagosan 10 kliens üzenetét olvassa, akkor üzenetek táblába havi kb 1500 rekord kerűl. Az állapot táblába 150 000. A két táblával számolni, keresni, műveleteket végrehajtani milyen terhelést jelent?
Jó lehet ez az irány? Esetleg máshogyan kellene megközelítenem?
Köszönök minden véleményt, kritikát, segítséget, tapasztalat megosztást!
Üdv!
Szerk.: Sorry srácok ezt lehet, hogy az adatbázisokhoz kellett volna, utólag is elnézést érte!
■ Most olvastam a hasonló témát, én is ilyesmivel ügyködök és a véleményetekre, tapasztalatotokra lennék kíváncsi.
Szóval a cél egy oldalon belüli üzenetkezelő rendszer, php + mysql.
Amit tudnia kell a rendszernek:
Lényegében, van 3 csoport user - kliens - admin. User azoktól a kliensektől kapja meg az üzeneteket, akiket követ. ( + admin, de ő természetesen nincs feltételhez kötve, minden usernek küldhet )
User és kliens között N:M kapcsolat van.
Az én elképzelésem, ameddig jutottam:
1. Ábrázoltam a kapcsolatokat külön ( nem csak a levelezés miatt kell )
kapcsolatok tábla: user_id - kliens_id
2. Van egy táblám az üzeneteknek:
msg_id, sender_id, subject stb
Na most user megkapja a "kapcsolata" alapján a kért leveleket, ez idáig stimmel.
Szeretnék állapotot is tudni a levelekről pl olvasott -> új üzenet érkezést jelezni, vagy törölt -> a user törölhesse a levelet a "saját listájáról".
Ehhez azt gondolom kell készítenem még egy táblát:
3. üzenetek_állapota tábla:
user_id, msg_id, status ( olvasott/törölt )
Akkor születne rekord, ha a user megnyitotta a levelet. ( ?? )
Na itt kezd kicsit sántítani a dolog nekem... Vélemény?
Ekkor, az "új üzenet érkezett" funkciót, ( képzeljük el ezt most fb -sen, piros boríték stb, nem ez a cél csak valami hasonló, lényeg hogy valahogy szeretném majd használni ), megkapnám a két tábla különbségeként, illetve listázáskor a törölteket levonva. DE ez a kezelés nekem elég macerásnak tűnik...
Kicsit utána számolva, ( ez nem egy éles project, de feltételezve igazi működést ) mondjuk 5000 user nél és 500 kliens nél, ha átlagosan 1 kliens havi 3 üzenetet küld és 1 user átlagosan 10 kliens üzenetét olvassa, akkor üzenetek táblába havi kb 1500 rekord kerűl. Az állapot táblába 150 000. A két táblával számolni, keresni, műveleteket végrehajtani milyen terhelést jelent?
Jó lehet ez az irány? Esetleg máshogyan kellene megközelítenem?
Köszönök minden véleményt, kritikát, segítséget, tapasztalat megosztást!
Üdv!
Szerk.: Sorry srácok ezt lehet, hogy az adatbázisokhoz kellett volna, utólag is elnézést érte!
Üzenet
JOIN
szükséges. MySQL és más SQL motorok esetén általában a táblába beszúrás a költséges, nem az olvasás.Lemaradtak a dolgok bocsánat.
Az "N:M kapcsolattal" akartam utalni hogy 1 kliens -> több üzi -> több user olvashatja. Tehát mindenképp kell a üzenetek állapota tábla! ( ? )
User-kliens kapcsolat tábla alapján kérem 1 usernek azokat az üzeneteket, üzenetek táblából , amiknek szerepel az id -je user-kliens -nél. De szeretném megjeleníteni, hogy user kapott e új üzit, illetve törölheti a saját listájáról az üzenetet, ergo csinálnék egy állapot táblát.
A kérdésem az lenne hogy ez a logika/megoldás helyes-e, működőképes?!
Az egyiket megválaszoltátok, elvileg ezt az adatmennyiséget gond nélkül kezelhetem!
Pár dolgot nem értek
A 150000 rekord nem sok - mint Poetro is írta -, viszont ez ugye havi szinten van. Egy év múlva 12 x 150000, ..., szóval valamiféle karbantartás szükséges lesz időnként, pl. archiválás. Ezzel már az adatbázis tervezésekor érdemes foglalkozni.
U.i.: igen, adatbázisokhoz kellett volna. :)
Kihagytam 1-2 dolgot!
Kihagytam pl: hogy az üzenet küldés egyirányú, csak kliens küldhet üzenetet usernek! Fordítva nincs üzenet! N:M kapcsolat = több-több kapcsolat, mindkét fajta egyedhez tetszőleges számú másik fajta egyed tartozik, arra akartam vele utalni, hogy user - kliens kapcsolatát mindenképp külön táblában kell ábrázolnom, nem így szokták hívni? Plusz kifelejtettem: természetesen userszám emelkedésével és/vagy kliens emelkedésével + idő, nő a rekordszám de persze lenne karbantartás, esetleg lejárata is bizonyos üzenteknek, ami után automatikusan törlődnek.
Szóval ahogy mondod nem feltétlenűl 12x150e egy évben.
Mysql-ben milliós
Ha jól sejtem azt szeretnéd megoldani, hogy az admin a hozzá tartozó mondjuk 300 juzernek egyszerre küldjön üzenetet, csak egy usernek nem tud, bár még az is megoldható.
A fenti logikád erre teljesen fasza,
SELECT * FROM message s JOIN message_status ms ON (ms.msg_id = s.id AND ms.user_id = ?)
ORDER BY ms.status;
Így a joinod hatékony lesz, csak az adott usernek az üzeneteit kapod meg, remélem nem rontottam el így reggel az első kávém előtt :)
Fenti select query esetében a status-ra egy indexet tenni kell, hogy gyorsabb legyen a lekérdezés.
még annyit, hogy lehet a
SELECT * FROM message_status ms JOIN message m ON (m.id = ms.msg_id) WHERE ms.user_id = ?
sőőőt, ez lesz a nyerő, sry, még csak most éledek.
Igen hasonlóan gondoltam én
Nem csináltam még ilyesmit.
Szerk.: Én is az első kávé előtt voltam... :)
Nem egészen erre, de a lényege hasonló.
CSAK User kaphat üzenetet, azoktól a kliensektől, akitől ő szeretne. ( 1 kliens írhat több üzenetet és 1 user kaphat több klienstől üzenetet ) Admin üzenetét mindenki megkapja.
( bár ez még kérdés hogyan építsem be ha egy tábla van összesen az üziknek, meg kell különböztetnem admint valahogy, esetleg másik tábla - most ültem neki. )
Igen egy usernek így ebben a felállásban nem tudok küldeni de elvileg nincs is rá szükségem. ( max mail meglátjuk )
Az üzenetek állapotát így külön táblába kell tennem, nem tudom besuvasztani sehova. Két lehetséges értéket szántam neki olvasott( mondjuk '1' ) / törölt ( '2' ).
Ha user bejelentkezik szeretném neki jelezni hogy van nem olvasott üzenete, ezért kell értelem szerűen olvasott státusz. Ha pedig megnézi az üzeneteket a töröltek nélkül kell az eredmény. Ezt próbálom ezzel az adatbázis szisztémával megvalósítani.
Nem lesz ez így jó...
Gyorsan átfutottam a dolgokat és ezzel a felállással csak azt lekérdezni pl bejelentkezéskor hogy van e olvasatlan üzenet úgy nézne ki hogy kapcsolatokból lekérdezem "követett" kliens_id -ket, ezekkel lekérdezem kliensek üzeneteit, majd ezt összevetem az üzenet státuszokkal és a státusztalan üzik lennének az újak, ha vannak. De ezt még hogy hogyan kapom azt nem tudom, kivonni nem lehet nem kompatibilisek az eredmény táblák, join -nal sem ezt az eredményt kapom. És ekkor még nem beszéltem a többi kezelésről.
Bár szanaszét volt ma a fejem, lehet hogy a megoldás itt van valahol előttem csak nem találom most. Mind1 holnap neki tudok ülni majd.
Addig is örömmel veszek véleményeket!
Köszönöm az eddigi segítséget is mindenkinek!
Üdv
túl bonyolítod
A státusz táblában minden user-hez, aki kapott a leválből van egy bejegyzés, igaz?
Amikor az "admin" elküldi a levelet, akkor kell kikeresni azokat a usereket, akik meg kapják a levelet a beállítások szerint. Ez egy lekérdezés, kapsz egy user listát. Majd szépen összeállítasz egy nagy insert query-t, egyszerre akár 1000 elemet is beszúrhatsz, tapasztalat szerint 1milcsi rekord eltart kb fél percig, vagy addig se.
Beérkezett levelek lekérdezése meg csak annyi, hogy user_id = ? AND status = <olvasatlan> => 0.0001 sec :)
Az adminnak még az is megmondhatod, hogy hányan nézték már meg a levelet.
szólj ha rosszul látom.
Eredetileg nem akartam rögtön
Ezért a bonyodalmam, de zsákutcának tűnik. Így ahogy írod könnyen le tudnám kérdezni, egyszerűen státusz szerint ez tiszta sor, csak így meg akkor azonnal minden userel fel kell vennem egy állapotot ugye, ezt el akartam kerülni ( bár gyakorlatilag ahogyan akartam az sem spórolós ) . Ez sem tűnik a legjobb megoldásnak. De ha máshogy nem megy ez még mindig maradhat.
Válaszidők
- Sok/kevés terhelés ill. idő elsősorban a vas és az adatbázismotor függvénye. Mivel előre sosem tudod az egyidejű látogatottságot, nem tudod, hogy egyszerre hány db erőforrásigénylésed lesz.
- Főleg fenti miatt, de egyébként is: erőforrással mindig érdemes "spórolni" (~optimalizálás), "legrosszabb esetben" villámgyors lesz a cucc. Persze ezt is okosan, nem a végletekig.
Kissé furcsállom ezt a fajta felállást.
Üzenetküldést (bármilyet) én inkább úgy tudok elképzelni, hogy a felhasználóknak vannak jogosultságaik (pl. tud üzenetet küldeni) és tartoznak 0-1-több felhasználói csoporthoz. Aki tud küldeni, az a megírt üzit tudja 1-több csoportnak küldeni. Itt a csoportokhoz rendelést a Júzerekre bíznám, a jogokat meg az adminra. (Végülis a "küldeni tudó" is lehet egy csoport, de akkor szoftveresen kell figyelni, hogy azt a Júzer ne választhassa magának.)
Ha valamelyik csoporthoz tartozik, akkor kapja és kész. Majd kiveszi magát a csoportból, ha nem kéri.
Az üzenetek táblában meg simán from_id, to_id, status, ...
Így is a küldés lesz a hosszabb, de az INSERT / UPDATE tudtommal minden motornál amúgyis jóval lassabb, mint a SELECT.
Ennek a megközelítésnek az előnye, hogy ugyanaz a Júzer könnyedén lehet küldő és fogadó is. Minden üzenet annyiszor van tárolva, ahányan kapják (ez rossz), de könnyedén lehet egyedileg kezelni a státuszt. Emiatt mondjuk lehet is szépíteni, hogy a tárgyat, üzenetet, feladót, stb. kiveszed másik táblába (vhogy úgy, ahogy csináltad).
És ez nem jelenti azt, hogy rossz lenne a te ötleted, ez csak egy másik.
Az első két pont miatt
Összecsapni már összetudtam volna, azért nem kellet volna sokáig tökölnöm :)
Ráébresztettetek, hogy nem jó ez az irány, ahogy leírtam nem teljesen felel meg
a tényleges működésnek. Most nekikezdtem kicsit máshogy, majdnem meg is van, holnapra csiszolgatom még, indexelek, lemérem és majd megkérdezem még 1x, hogy mit szóltok! :D
Köszönöm az időtöket!
OFF: Pepita, te ilyenkor dolgozol, vagy ilyenkor érsz rá?! :D
Irány
OFF:
Na jó, mostanában minden második héten (éjjel) olyan dolgom van, ami mellett tudok / van időm WL-ezni. A másik héten viszont annál kevésbé. Ne irigykedjen senki: nem egy rózsás helyzet, nem is publikus.