DevProTalk

DevProTalk (http://www.devprotalk.com/index.php)
-   SQL baze podataka - Sponzor: Baze-Podataka.net (http://www.devprotalk.com/forumdisplay.php?f=10)
-   -   NoSql baze i iskustva (http://www.devprotalk.com/showthread.php?t=11017)

_korso_ 22. 05. 2012. 12:35

NoSql baze i iskustva
 
U poslednje vreme (zadnje 2 godine) se sve vise prica o no-sql bazama. Iako izgledaju kao zgodan alat za neke stvari, sigurno da nisu zamena za RDBMS u svakoj situaciji.

Istrazivao sam malo na tu temu i cini mi se da su ove baze pogodne za neki tip web-based aplikacija, koje ne zahtevaju transakcije u isto vreme nad vise tabela (dokumenata), a npr. zahtevaju cesto radi prikaza ili izvestaja, agregaciju rezultata iz vise tabela (sto su tabele normalizovanije to je veca petljancija izvuci neke podatke). Kao primer, vrlo cesto zbog takve organizacije UI-a (sve na izvol'te) dolazi se u situaciju da treba da se radi JOIN nad 6-10 tabela, pa dodatno filtriranje, grupisanje, limiti itd... Nekada stvarno postaje PITA, a i sporo. Ok, tu su indexi i explain, ali voleo bih da bude nesto "lakse".

Govoreci no-sql terminologijom, to bi se pamtilo na nivou jednog dokumenta, jedne kolekcije, dok npr. stvari koje se mnogo cesto updateuju, ili rezultati nekih pretraga se mogu pamtiti u Redisu.
Siguran sam da ima i neki losih strana ovakve organizacije koje treba pokriti. Nisam testirao i radio u real-time uslovima sa ovakvim tipom baze, tako da sve sto bih izneo su manje-vise pretpostavke i razmisljanja.

Evo jednog linka, gde se uporedjuju neki od popularnih no-sql enginea: http://kkovacs.eu/cassandra-vs-mongo...uchdb-vs-redis

Gledao sam najvise MongoDB, posto je bas velika buka oko njega. Medjutim naleteo sam i na par clanaka na netu gde ljudi nisu najzadovoljniji istim (http://blog.engineering.kiip.me/post...r-with-mongodb, http://www.zopyx.de/blog/goodbye-mongodb - neki od argumenata su apsolutno validni). Dok, eto Trello ili stackexchange ga guraju uspesno.

Glavni zahtevi koje bi trebalo da podrzi no-sql baza su relativno lako skaliranje (master-slave), lakse pisanje tipova upita ili ubrzanje koji su pandan pisanju JOIN-a ili subselecta nad vecim brojem tabela u RDBMS svetu i uopste stabilno okruzenje da tako kazem (gde nece tek tako da podaci nestanu od sebe).

Sigurno cu se pozabaviti i sam vise ovim i istraziti i testirati neka resenja. Interesuje me da li je mozda neko imao iskustva sa ovim i naravno ako moze da to podeli :) ?

mangia 23. 05. 2012. 08:48

Mislim da daleko više pljuvačine možeš pronaći o MySQL-u recimo pa opet rula mnogo velike projekte...

Boj ne bije svijetlo oružje....

ivanhoe 23. 05. 2012. 13:00

Moje iskustvo sa mongom je odlicno, ali naravno ja nisam pravio Facebook (a ni Trello). Osnovna prednost u mom slucaju (tracking bannera) je sto su upisi stvarno brzi i sto ti NoSQL daje jednostavan nacin za organizaciju i kasnije dump podataka u komplexnu strukturu sa kojom je lako posle raditi.

Kod RDBMS moras da pravis komplikovane JOIN-e, pa da onda tako dobijene tabelarne podatke slazes u petlji u objekte koji ti trebaju, ovde je to vec tako kreirano u bazi i samo povuces ono sto ti treba. Em zahteva manje koda, em je dosta brze na vecoj kolicini podataka.

djipko 23. 05. 2012. 17:01

Jedna stvar koju ti ne kazu kada pocnes da radis sa nosql-om - koju bi i sam provalio ali mozda suvise kasno: UVEK cuvaj strukturu dokumenta u kodu i UVEK koristi polje za verziju scheme (ovo vazi ako ti podaci za koje koristis nisu ultra kratkog veka)

Sta pod tim mislim - za razliku od RDBMS-a, Mongo nema strukturu dokumenta (dakle CREATE tabele) - sto znaci da mozes u istu kolekciju da upisujes sta ti je volja... ova sloboda ce te ujesti pre ili kasnije tako sto ces imati kod sa 400 if-ova koji proveravaju da li dokument ima ovo ili ono.

Moj savet - definisi strukturu dokumenta u klasi (nesto kao jako tanki ORM), i ako mislis da ces menjati strukturu dokumenta - dodaj jedno polje koje oznacava trenutnu verziju (koje je recimo globalno i definise se na jednom mestu).

Kako kod i schema evoluiraju - sve promene ce se svoditi na to da u read() metodi procitas dokument - proveris polje 'verzija' i kastujes ga u odgovarajucu nasledjenu klasu tvoje osnovne ORM klase.

Ako nekoga zanima ili mu nije jasno na sta ciljam - mogu da bacim neki snippet da ilustrujem.

ivanhoe 24. 05. 2012. 16:22

^ dobar pristup, a jos jedan razlog za to da imas precizno definisan model, bar kod MongoDB-a, je sto on ne baca greske ako u upitu trazis polje koje ne postoji, tipa slucajno umesto counter otkucas coumter. A takve greske su uzasno teske za debug, narocito kod upita koji dohvataju podatke, jer je spelling otprilike poslednja stvar koju se setis da proveris (well, prvih 10 puta bar :) )

_korso_ 24. 05. 2012. 18:02

Koliko sam procitao i video, sa jedne strane no-sql daje fleksibilnost, dok sa druge strane (ako nisi disciplinovan i dosledan) mozes da upadnes u problem.
Dosta ljudi pominju da za razliku od mysql migracija, kod MongoDB-a koriste upravo verzije dokumenata, sto im omogucava laksi upgrade/izmene baze.

Citat:

Originalno napisao djipko (Napišite 107036)
Moj savet - definisi strukturu dokumenta u klasi (nesto kao jako tanki ORM), i ako mislis da ces menjati strukturu dokumenta - dodaj jedno polje koje oznacava trenutnu verziju (koje je recimo globalno i definise se na jednom mestu).

Kako kod i schema evoluiraju - sve promene ce se svoditi na to da u read() metodi procitas dokument - proveris polje 'verzija' i kastujes ga u odgovarajucu nasledjenu klasu tvoje osnovne ORM klase.

Ako nekoga zanima ili mu nije jasno na sta ciljam - mogu da bacim neki snippet da ilustrujem.

U sustini je jasno... ali ako te ne mrzi baci neki snippet - ne moze da skodi.

xippi 24. 05. 2012. 18:22

struktura dokumenta jednostavno mora da se cuva. ono sto je orm kod relacionih baza to je object/data mapping za nosql. sto se samog monga tice za asinhrono okruzenje postoji mongoosejs koji podrzava sheme, nestovanje istih, validaciju, itd. postoji nekoliko data mapping libova za rails i ostale jezike

_korso_ 24. 05. 2012. 19:06

ORM za no-sql baze mislim da se zove ODM (Object Document Mapper).
Potpuno mi je jasno da se trebaju u client kodu mapirati "definicije" baze (kolekcija i dokumenata). Kako radim sa custom napravljenim ORM alatom (koji je godinama peglan), upravo iz tih definicija se izvlace podaci za validaciju, za castovanje podataka na relaciji db-code, te za data migracije i za jos x stvari. Tako da mi je ideja kada i ako dodje do same implementacije, da se isti pristup primeni i za mongo ili neku drugu document bazu.

Za PHP postoji Doctrine ODM.

xippi 24. 05. 2012. 19:23

Citat:

Originalno napisao _korso_ (Napišite 107071)
ORM za no-sql baze mislim da se zove ODM (Object Document Mapper).

u pravu si

djipko 24. 05. 2012. 20:13

Naravno da postoje razni gotovi mapperi ali svaka dodatna biblioteka u projektu zna da ima i svoju cenu. ODM-i nisu teski i mogu biti zabavni za pisanje, posebno ako ti za tvoje potrebe ne treba sva masinerija koju nude OSS resenja.

Posto sam obecao primer evo ga za python. Primer je vrlo jednostavan mada ovo sve moze mnogo vise da se zakomplikuje.

Dakle osnovna klasa i globalno mesto gde se registruju modeli i verzije bi bili u modulu koji bi izgledao otprilike ovako:

Kôd:

from pymongo import Connection

version_reg = {} #"Globalni" dict koji cuve verzije

def register_version_model(cls, version):
    """Registruj klasu koja je model za odredjenu verziju scheme"""
    version_reg[version] = cls

def get_version_by_model(cls):
    """Vrati za koju verziju scheme je registrovana klasa"""
    for v, c in version_reg.iteritems():
        if c is cls: return v
    return None
   
class MongoBaseModel(object):
    """Klasa koju svi mongo modeli nasledjuju, i redefinisu potrebne metode"""

    _db = 'test_db'
    _collection = 'test_col'

    def _to_dict(self):
        """
        Ova metoda mora da se redefinise - ona ustvari
        sadrzi logiku predstave modela u bazi.
        """
        raise NotImplementedError

    def save(self):
        #Napravi od sebe dict
        d = self._to_dict()
        #vidi gde si registrovan, i zapisi to u bazu
        d['version'] = get_version_by_model(self.__class__)
        Connection()[self._db][self._collection].insert(d)

    @classmethod
    def read(cls, spec):
        """
        Metoda procita dokument ako postoji, i na osnovu verzije konstruise
        objekat i vrati ga
        """
        doc = Connection()[self._db][self._collection].find_one(spec)
        if doc:
            model_cls = version_reg.get(doc['version'], None)
            if not model_cls:
                raise ValueError("No model registered for this version")
            return model_cls(doc)
        return None

I onda zatim pravis svoj model (evo ga jako jednostavan primer):

Kôd:

class Calculation(MongoBaseModel)
    """Zamisljena klasa kalkulacije ciji se rez cuva u bazu"""
    def __init__(self, doc):
        self.date = doc['date']
        self.result = doc['result']
   
    def _to_dict(self):
        """Obrnuto od konstruktora - u ovom primeru nezanimljivo"""
        return dict(
            date = self.date
            result = self.result
        )

Koji i registrujes sa:

Kôd:

register_version_model(Calculation, 1)
E sada kada je model potrebno malo izmeniti:

Kôd:

class NewCalculation(MongoBaseModel)
    """Nova klasa kalkulacije koja sada cuva i koliko je kalc trajala"""
    def __init__(self, doc):
        self.date = doc['date']
        self.result = doc['result']
        self.duration = doc['duration']
   
    def _to_dict(self):
        """Obrnuto od konstruktora - u ovom primeru nezanimljivo"""
        return dict(
            date = self.date
            result = self.result
            duration = self.duration
        )

register_version_model(NewCalculation, 2)

Ono sto se ne vidi iz primera je da ako ove dve klase nasledjuju od trece klase koja definise neki interfejs za rad (i pegla nesuglasice) - potpuno si se resio glavobolje tipa - "sta sam to procitao??". Nekad je OO i dobar :)

Kao sto sam rekao moze ovo mnogo vise da se zakomplikuje i nabudzi (metaprogramiranjem i slicnim cakama), naravno fale provere gresaka itd. ali funkcionalni, mali i lagani ODM ne trazi mnogo vise od ovih 30ak linija u Pythonu, bez da se patis sa nekim bloat-om sa github-a.

Ako nekome neka python-specific caka nije jasna (mada ih bas i nema u gornjem kodu) rado cu pojasniti.

_korso_ 27. 05. 2012. 11:47

^ Hvala puno na trudu i primeru.

Primer je u sustini jasan, posto ima i inline komentara. Mada moze se kao sto kazes zakomplikovati, sto validacijom, sto meta definicijama, a sto jos nekim apstrakcijama. Sto vise automatizma i magicnih stvari to ce biti i kompleksnija implementacija.

Imao bih samo jos 2 pitanja, posto vidim da imas iskustva sa MongoDB-om.

Kako se sajt ili app (ne znam da li je jedna ili vise koje si radio) ponasaju ukoliko ima malo veceg opterecenja istih - npr. par stotina konkurentnih zahteva u sec? Najvise mislim na race-conditions posto koliko sam shvatio, MongoDB zakljucava celu bazu dok se za jednog korisnika obradjuju podaci?

Da li si naisao na jos neke da kazem "klopke" kojih nema u RDBMS svetu. Jedan od primera je ovo verziranje polja. Drugi... video sam na par mesta kada se prave polja u bazi, da samo ime zauzima resurse baze. Ako imas 1000 korisnika u kolekciji users, "username" polje se 1000x pamti, da tako kazem. Pa onda radi optimizacije i performansi npr. mapiraju ga u "usn", pa ga onda "remairaju" u username u samom server/client kodu. Na ovaj nacin (procitah pre neki dan, ne secam se gde) neko je bazu sa 700MB, smanjio na 300MB, sto je vise nego pola.

djipko 27. 05. 2012. 14:18

Nema na cemu :)

Sto se tice prostora - moj primer je tu uzasno neefikasan jer za SVAKI record cuva verziju. Ovo je nesto sto bi radio u pocetku razvoja, kada postoji velika mogucnost da ces imati izmena same scheme, ili ako ne maris previse za prostor (Mongo je inace vrlo "bahat" sto se prostora na disku tice, barem sa default parametrima, a i ne zaboravimo da po defaultu dodaje svoj _id na svaki record, tako da ako ti je prostor problem - sigurno moze bolje od onoga sto mongo radi po defaultu).

Sto se lockovanja tice, mislim da to zavisi od tvog deployment-a. Mongo nije MySQL i sfere u kojima se oni koriste nisu skroz disjunktne, ali se i ne preklapaju u potpunosti. Opisacu ti ukratko kako ga mi koristimo, ali po meni svaki slucaj je drugaciji. Ako mene pitas nakon nekog vremena sam poceo da razmisljam da je Mongo u klasi sa Memecahced-om (samo nabudzen) bre nego sa raznim RDBMS-ovima.

Dakle: mi koristimo ReplicaSet opciju gde imamo master u koji se pise (to ne rade web workeri, nego za to koristimo taskove - za queue inace isto koristimo mongo :) ali to je nevezano za celu pricu). Front end web serveri imaju svaki svoj mongo koji replicira mastera, i u te mongo-e se nikad ne pise (osim replikacije naravno ali je ona jako brza) vec samo cita iz njih. Dakle lag replikacije postoji (otud ona rec 'eventual' u frazi 'eventual consistency'), ali je nama nebitan, dakle kao sto rekoh zavisi od aplikacije (mi imamo peakove sa nekoliko stotina upisa, ali realnost je par desetina u sekundi).

Sami upisi na mastera su uzasno brzi - ali kad kazem uzasno mislim jako uzasno, hiljade u sekundi, pre ce ti algoritam biti bottleneck nego Mongo.

Ovo sve sto sam ti opisao sa ops strane nije trivijalno, ali nije ni nocna mora (Mongo ReplicaSet nije bas jednostavan za koriscenje, srusio nam je sajt 2 puta dok nismo provalili kako bezbolno da dodajemo servere, ali se sve zavrsilo na fabric skripti od par stotina linija koja to sada vrlo bezbolno radi).

Sto kazu ono TL;DR:

Mongo je okej sistem, ima svoje mracne strane, ali u definitivno vise nego pristojan. Sve zavisi od tvoje aplikacije, ali kad razmisljas o tome gde da ga koristis (a i vecinu nosql resenja), pre razmisljaj: memcached sa vise opcija a slabijim performansama (isto pogledaj i Redis), nego felksibilniji MySQL.

PS. Nije bas tako strasno sto zakljucava celu bazu - pogledaj http://www.mongodb.org/display/DOCS/...ncurrency+work ali ako ti je to problem mozda ti treba redizajn :).

_korso_ 28. 05. 2012. 09:20

Prostor na disku nije problem, mada bez obzira na to nismo za rasipanje resursima.

Inace Redis ce verovatno biti u stacku posto nam je potreban pub-sub za real-time.
Pa su sada varijante, nosql ili Mysql, gde bi one stvari koje su usko grlo, ako je nosql isle manje u Redis (posto pomenuh da je vec skoro izvesno clan stacka i da moze da radi i kao Memcache), ili ako je Mysql onda bi vise stvari imalo neki vid predstavljanja u Redisu.
Sustina je da posto ce biti dosta sadrzaja u vidu agregacije da tako kazem, da ubrzamo i sprecimo masivno pisanje JOIN-ova nad x tabela. Trenutno nemamo bazu, pa mi je jedan od ciljeva da sada ako moze identifikujemo stvari kojih se treba paziti ili obratiti vecu paznju ako radimo sa MongoDB-om (slicno sto si pomenuo da ti niko nije rekao da treba verzirati polja).

U svakom slucaju, jos jednom ti hvala puno na trudu i vremenu. Imao bih jos par pitanja, ali neka budu ovo za sada. Dosta si mi pomogao i ovako :).

djipko 28. 05. 2012. 10:53

Meni zvuci super zanimljivo to sto pokusavate (ako sam dobro razumeo). Moj savet - probajte prvo braindead pristup - memcached ispred mysql-a sa lukavo odabranim diskriminatorom... dobre su sanse da ce vas samo to daleko odvesti.

Ja sam uvek protiv komplikovanja ako nije bas nuzno :)

_korso_ 28. 05. 2012. 11:57

Slazem se sa tobom. I mi smo za KISS :).

Odatle i npr. odluka da ne koristimo Memcache, kada vec imamo u stacku Redis koji moze da potpuno zameni Memcache funkcionalnost.
Problem kesiranja, pub-sub resen - barem na papiru.

Sada sama baza - persistence sloj. Nemamo iskustva za Mongom, ali imamo sa par RDBMS. Znamo sta nam je problem u RDBMS-u, ali ne znamo u Mongou. Jeste brzi za stvari koje nam treba (JOIN replacement), jeste donekle parsovanje rezultata na relaciji db-app lakse (strukture objekata vec cuvamo u MongoDB onakve kakve ih "skoro" i koristimo), ali opet nemamo nijedan nosql production projekat, pa imamo nepoznanice.

Videcemo...


Vreme je GMT +2. Trenutno vreme je 10:13.

Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.

Mišljenja, saveti, izjave, ponude ili druge informacije ili sadržaji nastali na Sajtu su vlasništvo onoga ko ih je kreirao, a ne DevProTalk.com, tako da ne morate da se oslanjate na njih.
Autori poruka su jedini odgovorni za ovakve sadržaje. DevProTalk.com ne garantuje tačnost, kompletnost ili upotrebnu vrednost informacija, stavova, saveta ili datih izjava. Ne postoje uslovi pod kojima bi mi bili odgovorni za štetu ili gubitak koji je posledica bilo čijeg oslanjanja na nepouzdane informacije, ili bilo kakve informacije nastale kroz komunikaciju između registrovanih članova.
Web sajt može sadržavati linkove na druge web sajtove na Internetu ili neke druge sadržaje. Ne kontrolišemo niti podržavamo te druge web sajtove, niti smo pregledali bilo kakve sadržaje na takvim sajtovima. Mi nećemo biti odgovorni za legalnost, tačnost ili prikladnost bilo kog sadržaja, oglasa, proizvoda, usluga ili informacije lociranim na ili distribuiranih kroz druge web sajtove, niti za bilo kakvu štetu nastalu kao posledica takvih informacija. DevProTalk.com drži i čuva druga prava vlasništva na web sajtu. Web sajt sadrže materijale zaštićene copyright-om, zaštitne znakove i druge informacije o pravu vlasništva ili softver. Članovi mogu poslatu informacije zaštićene pravima vlasništva njihovih nosilaca i ona ostaju zaštićena bez obzira da li su oni koji prenose te informacije to naveli ili ne. Osim informacija koje su u javnom vlasništvu ili za koje dobijete dozvolu, nemate pravo da kopirate, modifikujete ili na bilo koji način menjate, objavljujete, prenosite, distribuirate, izvršavate, prikazujete ili prodajte bilo koju informaciju zaštićenu pravima vlasništva. Slanjem informacija ili sadržaja na bilo koji deo DevProTalk.com, Vi automatski dozvoljavate i predstavljate garanciju da imate pravo da dozvolite DevProTalk.com ili članovima DevProTalk.com bespovratnu, kontinualnu, neograničenu, globalnu dozvolu da koriste, kopiraju, izvršavaju, prikazuju i distribuiraju takve informacije i sadržaje i da iz takvih sadžaja koriste bilo koji deo u bilo koje svrhe, kao i pravo i dozvolu da koriste gore navedene sadržaje. Svi zaštitni znakovi (trademarks), logotipi, oznake usluga, firme ili imena proizvoda koji se pominju na ovom web sajtu su vlasništvo kojim raspolažu njihovi vlasnici.