Mongo - nagy adatmennyiségnél melyik megoldás lenne a jobb?

hali,

épp egy tárolási problémával küszködök, és kéne némi tapasztalati vélemény.

az van, hogy van 50E+ user, nekik pedig vannak kapcsolataik egymással -- kivel leveleztek, ki nézett meg kit, ki kedvel kicsodát, stb. ez kb. 3-4M kapcsolati rekord.

mivel igen aggresszíven cache-elek (hogy ne kelljen átnézni állandóan ezeket a kapcsolati rekordokat), így az van, hogy tároláskor és cache-újraépítéskor kell csak a backendhez nyúlnom, ami jelenleg megosztva file (userenként 4 file) és mysql tábla (kapcsolatonként (típusok szerint is) 1 rekord).

mivel nemrég clusteresedtünk, ezért a file backend nfs-re került, de az nagyon omladozik a terhelés alatt (mivel leginkább írási műveletek történnek), így átmenetileg visszakoznom kellett a terheléselosztásos php módszertől. innentől eléggé egyértelmű, hogy a file backendet meg kell szüntetnem, és át kell raknom valamilyen db alapra. a mongot gondoltam kipróbálni erre, főleg, mert memóriában tudja tárolni az igazán aktív rekordokat.

a nagy gondom az, hogy melyik tárolási forma lenne a célszerű.

ha user/kapcsolattípus alapján 1-1 rekordot tárolnék (mint a klasszikus sql alapon), akkor legalább 3-4 millió rekordról lenne szó, ahol minimum 3 indexet kéne fenntartanom (user1 id, user2 id, típus) a hatékony lekéréshez -- ez viszont a cache-elés miatt nem tűnik annyira fontosnak.

a másik variáció az, hogy userenként 1 rekordot tartok fent, amin belül mondjuk json-ba kódolva a jelenlegi fájlok (illetve sql-ben tárolt adatok) tartalma kerül. ez kb. 50E+ rekordot jelent. így csak egy indexet kellene fenntartanom, a user ID-t. így persze vesztem azt, hogy szabadon csináljak lekéréseket a db-ben, de mint az a fentiekből látható, ez most sem lenne megoldható, és nincs is rá szükség. viszont így egy-egy entry viszonylag nagyobb méretű lehet, és kell némi logikát alkalmaznom a betöltéskor/mentéskor, plusz saját logikával kell átnéznem és módosítanom a "file" tartalmát.

per pillanat hajlok az utóbbi felé, mert attól tartok, az előbbinél a rekordok száma miatt az indexek nagyon sok operatív memóriát falnának fel, és eléggé fontos lenne, hogy minél több minden férjen be a ramba.

ti melyiket választanátok?

Hozzászólások

Kapcsolatokat leirni nem lenne celszerubb graffal? Pl.: Neo4j

Bocs, rájöttem, hogy nem értem. Illetve kapizsgálom, de nem tudom megragadni a problémát, mert nekem egy rakat kérdőjel az, hogy egyáltalán miért alakult így a rendszer.

Egy file megnyitasa es benyalasa diszk-rol kb. 10x gyorsabb, mint egy mysql select.

Mi egy alkalommal, amikor egy gyors, perzisztens es egyszeru "adatbazis"-ra volt szukseg, siman raktunk 2-3M softlinket egy konyvtarba. Miert? Mert ha tudod a pontos nevet az entry-nek a konyvtarban (a.k.a. a hash "kulcsat"), akkor az ext3/4 bazigyorsan megtalalja a dir_index miatt, a hash "erteke" pedig a softlink miatt az inode-ban van, tehat a readlink() mar memoriabol tudja rogton kiszedni. Ez igy egy bazigyors hash-t eredmenyez, ahol az adat az ext3 inode-jaban tarolodik, es 1 db inode lookup az eleres koltsege (amit raadasul kernelben megy, okosan cache-elve, szoval bazigyors).

Backup/restore/stb... ertelemszeruen megoldott tar-ral.

Ugyanezt megprobaltuk mysql-lel is: 10-50x lassubb, 10-50x tobb diszket foglal, backup/restore nehezkes a hulye mysqldump miatt, es a mysql + client lib egy halom eroforrast eleszik meg monitorozni is kell.

Tanulsag: ne becsuld ala az egyszeru megoldasokat. :)

Nehéz elképzelni, hogy ebben a rendszerben a bottleneck egy jól indexelt key->value lookup az SQL-ben. Feltételezem, hogy a 4 fájllal-, illetve a jövőben a mongodb-vel való munka nagyságrendekkel költségesebb.

De igazából mindegy, azért is töröltem a hozzászólást, mert nagyon sok lenne a feltételezés, bármit is javasolnék.

Esetleg annyi, hogy azt írja, hogy rengeteg írás van, ez okozta a problémát. Ha összevonja az objektumokat, nem lesz mégtöbb fölösleges írás? Ha a 4 fájl eddig is egyszerre volt felülírva akkor nem, de ha külön-külön, akkor most a módosítás jóval több írással jár mint eddig. De mennyi adatot jelentenek a fájlok összesen egyáltalán? Kitudja..

"a mongot gondoltam kipróbálni erre, főleg, mert memóriában tudja tárolni az igazán aktív rekordokat."

Másodszor átolvasva is itt döccentem meg.
Nem vagyok egy univerzális db-látó, de azért merem állítani, hogy minden motornak tulajdonsága és kötelessége, hogy az általad neki szentelt memóriában/cache-ben/bufferpoolban/ahogyépphívjákban az igazánb aktív rekordokat tartsa (lévén azoknak nagyobb az esélyük arra, hogy az (n-1). utasítás tárgyai is voltak.

Ez a hitem meg arra a gondolatra vezetne, hogy a mongo pont annyira jó választás, mint bármelyik, ahol a bpool adjusztálható. Azaz, a mongo esetében ez pont nem igaz, mert viszi, amit talál, de ha egyedül játszik a pályán, ez nem gond.

Hogy én 10* előbb olyan megoldást választanék, amelyben SQL a lekérdezőnyelv, és csak nyomós ok esetén egyebet, azt betudom az őszülő szakállamnak.

Esetleg mysql cluster? (nem a Percona, hanem az ndb backendes)
Nem látom, hogy mi szól a Mongo mellett, ha noSQL-t kéne élőben használnom, inkább mennék valami olyan irányba amit élesben is sokan használnak. (Cassandra?)

1) nfs-t felejtsed el gyorsan, bármi is van mögötte storage-nek. home-ot felrakni jó, bármi másra, ami terhel is: halál.
2) json-t ne tárolj mezőben, mert igen szopó lesz select-ben szűrni az alapján.
3) Mekkora az adatbázis? Él leírásánál a 4M rekord (int,int,enum) esetén kb 50 mega lehet, + 3 index az fejenként köbö ugyanennyi. Ennek röhögve el kéne férnie a kernel bufferbe. Emellett a select-jeidet nézzed meg, hogy _TényleG_ használják-e az indexeket, ég és föld a két véglet.
4) mysql külön gépre.

Ezek után kezdd a mysql-t clusterezni.

na de épp ez az, hogy igazándiból nincs szükségem szűrésre, kondíciós selectekre, ezért gondoltam valami nosql-es megoldásra.

az 50 mega túl optimista szám. jelenleg a file backenddel a csak ezzel foglalkozó rész du -s -h-ra 3GB-ot ad, amin egy sql-ben a kapcsolat típusa mint enum persze spórolhatna, de jó eséllyel úgy max 1GB-ot.

Mongo-ek csinalnak free online mongo kurzusokat, javaslom erosen, mert nagyon jok! (nekem mar megvan)

Van egy kulon szekcio dedikalva pont a kerdesednek: hogyan a legcelszerubb az adatokat mongo-ba pakolni?

Javaslat az, hogy 1 objektumot tegyel egy dokumentumba (regiesen rekordba). Az osszes kapcsolataval egyutt, amire altalaban szukseged lesz. Igen, ez igy nagyobb, de akkor is csak 1 objektum, nem 4000. Mongo jobb szereti, ha visszaad neked egy blob-ot es te csinalod a tobbi melot.

Na persze ez csak okolszabaly. Az iskolapelda egy blog bejegyzes volt: ott a blogentry melle beletettek az osszes kommentet. tehat kb. igy:

{
blogpost: {},
comments: [{},{}]
}

Ha uj komment jott, siman push a comments-be, megjeleniteshez meg ugyis kell az osszes komment.

Mint a peldabol lathato, gondolkodni kell: hogyan tudod ugy szervezni az adatokat, hogy minimalizald a muveleteket es a lekerdezett dokumentumokat a leggyakoribb hozzaferesi mintaknal.

BTW mukodhet a 4000 rekordos megoldas is az aggregate framework miatt, ha kellokepp el tudod osztani a terhelest (=nincs order meg hasonlo a pipeline-ban, ami kikenyszeritene az egynode-os feldolgozast). Viszont az aggregate framework teljesitmenye nem osszemerheto egy compiler-evel, ugye, a lehetosegei meg plane nem.

YMMV.

tulképp itt bejátszik még a PECL-ös mongo db driver PHP alatt is. ha a mongo natív json/bsonját használom, akkor a en/dekóding tereh a mongón van (gondolom), viszont ha sima blobot dobok bele, akkor elvileg a PHP oldalon kell majd birkózni ezzel, ami nekem első blikkre szimpatikusabb, mert több app szerver van (2), mint db backend (1).

BTW, gondolkozhatsz egy HDFS-en is. Igen, tudom, hadoop borzalmas, de a hdfs resze meg nem kifejezetten (van hozza fuse modul is), viszont distributed es megbizhato. Egy gyors probat meger nfs helyett, mielott beleasod magad egy mongo cluster-be. :)

Megtörtént már az átállás?

Ha igen, akkor mik a tapasztalatok?