Direct naar content

MongoDB of PostgreSQL voor een web applicatie

PostgreSQL, zoals alle SQL databases (including SQLite), is een relationale database. PostgreSQL is gespecialiseerd in het bijhouden van relaties tussen stukken data en helpt je data op te zoeken wanneer je iets kent dat eraan gerelateerd is.

Bijvoorbeeld, stel je hebt twee database tabellen, “Users” voor alle gebruikers en “Posts” voor alle berichten die gedaan worden door een gebruiker, met “Posts.user_id” als foreign key reference naar “User. id”. Je hebt een schema waarin 1 Post slechts 1 User kan hebben, en logisch gewijs, 1 User kan meerdere Posts hebben (omdat Users zelf geen relatie heeft met Posts, de relatie is de andere kant op). SQL maakt het heel makkelijk om met zulke relaties te werken. Je kunt zeggen “geef me alle Posts van een bepaalde User”, of “geef me de User van deze Post”.

Martijn Wallet

Principal DBA Consultant
Ellert van Koperen

MongoDB of PostgreSQL?

Alle SQL databases kunnen omgaan met relationele queries zoals hierboven beschreven, maar PostgreSQL is er wel heel erg goed in. Er is echter ook een aspect waarmee PostgreSQL niet erg goed mee kan omgaan: graphs. Daar komen we verderop op terug.

De Users en Posts relatie hierboven is een voorbeeld van een “one-to-many” relationship (of “many-to-one” afhankelijk van welke kant je er naar kijkt). Er is ook zoiets dat een “many-to-many” relationship heet, deze is gebaseerd op een combinatie van een “many-to-one + one-to-many” relatie.

In ons hypothetische voorbeeld van Users en Posts zouden we kunnen stellen dat een Post meer dan 1 User heeft door het volgende te definieren: “Users Posts” waarbij deze nieuwe “Users_Posts” tabel twee kolommen heeft, 1 met een foreign key relatie naar een record in Users, en een andere met een foreign key relatie naar een record in Posts. Voor elke unieke combinatie van User en Post kan een record worden toegevoegd aan de Users_Posts tabel die de gebruiker en het bericht met elkaar verbinden.

Hier is nog een ander veel voorkomende situatie waarin je zo’n model nodig hebt: Films met hun Acteurs in beeld brengen. Je hebt dan een tabel voor Films en Acteurs, maar ook een tabel die ze met elkaar verbindt.

Laten we zeggen dat je wilt weten in welke films de acteurs A en B samen spelen. Dat is makkelijk:

SELECT * FROM Films

WHERE id IN (SELECT film_id FROM Films_Acteurs WHERE acteur_id IN (B))

AND id IN (SELECT film_id FROM Films_Acteurs WHERE acteur_id IN (B));

Heb je gezien wat we deden? Dit heten nested queries. Beginnend bij het binnenste, we vroegen naar alle film_ids in de join tabel die A bevatten en die B bevatten, vervolgens vroegen we naar alle details uit de Films tabel voor de gevonden film_ids in het voorgaande.

Maar wat als wat als A en B nooit samen in een film hebben gespeeld maar je weten wilt of ze overeenkomende co-acteurs hebben? Dit is zoals LinkedIn en Facebook werken, waar je een profiel zoekt van iemand die geen vriend is, maar LinkedIn en Facebook kijken naar gemeenschappelijke vrienden.

Dit is een graph search patroon en iets voor een totaal ander type database genaamd graph database. Bijvoorbeeld Neo4J is zo’n type database. Hoewel graph data gemodelleerd kan worden met een relationele database zoals PostgreSQL kun je beter gebruik maken van een database type die daarvoor ontworpen is zoals Neo4J.

En dan is daar MongoDB. Waar is die dan voor bedoeld? MongoDB is geen graph database, of relationele database. Zoals CouchDB is het een document database en vertegenwoordigd het tegenovergestelde. Wat zou je doen als je alle details van een film op 1 plaats wilt opslaan en helemaal niet van plan bent om de data onderling te vergelijken. een relationele database wil dat je je data “normaliseert” door elk klein detail in een aparte tabel op te slaan, maar dat zou je irritant kunnen vinden.

Je wilt gewoon data op 1 plek opslaan zonder jezelf al te druk hoeven te maken. Je bent nog bezig om uit te zoeken welke data je eigenlijk wilt opslaan, dus voor nu stuur je het gewoon ergens heen en over het querien/bevragen kun je je later zorgen maken. Dat is precies waar document databases voor bedoeld zijn en daar is MongoDB goed in.

Tegenwoordig heeft PostgreSQL veel stabiele extensions beschikbaar zoals store, arrays en JSON datatype voor kolommen, zodat men ook document georiënteerde features kan implementeren in PostgreSQL. PostgreSQL is stabiel en snel. De keuze is ook afhankelijk van programmeer taal die gebruikt wordt. Sommige libraries ondersteunen Postgres, maar geen Mongo. Wanneer zou MongoDB wel echt de betere keus zijn?

De meeste antwoorden op deze vraag schieten voorbij aan het belangrijkste aspect. PostgreSQL heeft hele goede native key/value en JSON support, dus als je “schemaless” wilt gaan en datamodellering pas wilt toepassen als je al een “heap of data” hebt, zou je gewoon een HStore/JSON kolom kunnen gebruiken en data daarin opslaan.

Je kunt daarnaast schema’s gebruiken op andere tabellen en hoofdbrekens voorkomen over het gebruik van meerdere verschillende database platformen. PostgreSQL heeft het JSON data type geïntroduceerd in versie 9.2 en het meer efficiente JSONB type in 9.4. Je kunt dus een mix van relationele en document data gebruiken in PostgreSQL zelf.

En dan nog iets anders … High availability is niet hetzelfde als een schrijf snelheid, eigenlijk gaan ze niet samen. Super snelle “write throughputs” kunnen met MongoDB behaald worden door het schrijven naar disk uit te stellen tot een later moment. Dat maakt het mogelijk dat je data verlies kan oplopen, het tegengestelde van beschikbaarheid. PostgreSQL heeft deze voorzieningen niet en is wellicht niet interessant als je geen waarde hecht aan duurzaamheid van je data.

Vanaf versie 9.4 PostgreSQL benchmarks tonen aan sneller te zijn dan MongoDB voor zowel schrijven als lezen van JSON data. Zie hiervoor ook Postgres Outperforms MongoDB and Ushers in New Developer Reality (hoewel er geen twijfel bestaat dat beide databases nog verder te tunen zijn voor specifieke scenario’s).

Hier is ook informatie te vinden over een keuze in deze: