
Tom Hollevoet
Bij het ontwerpen van een Drupal-website kiest men vaak voor een relationele database om de data van een website te bewaren. MySQL is daar een goed voorbeeld van. Maar vanaf men veel data bezit, met een grote hoeveelheid aan velden, is een relationele database niet meer performant genoeg. In zo'n situatie is het interessant om te kiezen voor een NoSQL-database, zoals MongoDB. Maar wat zijn nu juist de grote verschillen tussen een relationele en een NoSQL-database? Wij lichten dit graag even voor je toe.
Bij het installeren van een Drupal-website zal er standaard gekozen worden voor een relationeel database management systeem (RDBMS). Meestal wordt er voor een MySQL-database gekozen, maar andere relationele databases die beschikbaar zijn voor Drupal zijn MariaDB, SQLite en PostgreSQL.
De data waarover men beschikt, wordt opgeslagen in verschillende tabellen. In deze verschillende tabellen wordt de data dan verdeeld over verschillende kolommen.
In een RDBMS kan een tabel een relatie hebben met de tweede tabel. Zo kan een tabel 'cities' een verwijzing hebben naar de tabel 'countries' door middel van een foreign key, een sleutel die verwijst naar een andere tabel.
Tijdens het creëren van velden op een content type, worden verschillende tabellen aangemaakt in de database. Bijvoorbeeld voor het content type 'Person', met velden 'field_person_name', 'field_person_email' en 'field_person_country', zal men drie tabellen terugvinden in de MySQL-database.
In Drupal is het echter mogelijk een relatie te maken naar een ander content type, door middel van een 'Entity Reference'-veld. In bovenstaande voorbeeld is 'Country' een content type en is 'field_person_country', een entity reference-veld.
In de back-end van Drupal zal de data van een bepaalde node opgehaald worden door een SELECT query met verschillende JOINs naar de verschillende velden en tabellen. Hoe meer JOINs er moeten toegepast worden bij een query, hoe meer tijd het zal kosten om deze query uit te voeren. Aangezien een RDBMS verticaal geschaald is, zal men de resources (CPU/RAM) van de webserver moeten verhogen om de snelheid en de haalbaarheid van deze queries te verhogen.
Indien een bepaalde node 500 velden bezit, dan moeten er in de back-end 500 JOINs uitgevoerd worden. Dit kan leiden tot performantieproblemen. De webserver moet een grotere capaciteit hebben om deze query uit te voeren, en de uitvoertijd van deze query zal meer tijd in beslag nemen. In zo'n situatie is een relationele database geen goeie optie meer. Een NoSQL-database is dan een betere keuze.
Bij een NoSQL-database gebruikt men niet langer de typische JOINs die voorkomen bij een RDBMS. De data wordt niet meer opgeslagen in verschillende tabellen, maar bij de NoSQL-database zal de data worden opgeslagen in verschillende structuren zoals documents en collections.
Het grote voordeel van NoSQL is dat het horizontaal geschaald kan worden. Dat betekent dat de load kan verdeeld worden over de verschillende resources van de webserver.
MongoDB zal de data opslaan onder de vorm van een documentstructuur. Een document is te vergelijken met één grote JSON-file, waar de data opgeslagen wordt aan de hand van veldnamen en waardes. Zo kan een veldnaam heel snel aangepast worden en moet, zoals bij een RDBMS, niet de tabelstructuur worden aangepast. De data zit dus in één document en is niet langer verdeeld over verschillende tabellen, wat bij een RDBMS wel het geval is.
Voor Drupal 6, 7 en 8 is er een contrib module die de mogelijkheid biedt om Drupal-data op te slaan in MongoDB. De contrib module heeft verschillende submodules om verschillende functionaliteiten van Drupal in een MongoDB-database te implementeren.
Door deze verschillende submodules kan de functionaliteit cache, field_storage, session, watchdog, block en/of queue opgeslagen worden in een MongoDB-database, en niet meer in een RDBMS zoals MySQL.
Het zijn één of meerdere van bovenstaande functionaliteiten die opgeslagen worden in de MongoDB-database. De andere functionaliteiten en (standaard-) tabellen van Drupal blijven opgeslagen in de RDBMS (MySQL). Dit betekent dat de RDBMS nog steeds gebruikt zal worden.
In dit artikel zullen we de field_storage submodule van naderbij bekijken.
In Drupal 7 is er in de RDBMS (MySQL) een 'field_config' tabel waar alle veldconfiguratie (machine name, type veld, cardinaliteit...) opgeslagen zit. In deze tabel is er ook een storage_type/storage_module-kolom aanwezig. Standaard staat dit bij een Drupal installatie ingesteld op field_sql_storage, zodat de data van deze velden opgeslagen worden in de RDBMS.
Van zodra je kiest om de mongo_field_storage contrib submodule te installeren, zullen nieuwe velden aangemaakt worden met als storage_type/storage_module waarde mongodb_field_storage. Deze instelling wordt standaard geïnstalleerd bij het activeren van de mongo_field_storage module door de Drupal variabele field_storage_default gelijk te stellen aan mongodb_field_storage.
In de backend van de mongodb_field_storage module zijn er verschillende 'hook_field_storage_X' functions terug te vinden die opgeroepen worden bij de velden die mongodb_field_storage als storage_module/storage_type hebben.
De belangrijkste implementaties zijn:
De belangrijkste verandering in vergelijking met MySQL is dat een node zal opgeslagen worden als één groot document en niet meer verspreid over verschillende tabellen.
De node wordt nog steeds met zijn Node ID en andere parameters opgeslagen in de node-tabel in het RDBMS. Alle data van de velden van de node worden opgeslagen in MongoDB. Per node zal er één document aangemaakt worden.
Het grote voordeel is dat bij het ophalen van een node, slechts één document moet opgehaald worden uit de MongoDB-database. Bij de standaard RDBMS zouden er voor vijfhonderd velden effectief vijfhonderd verschillende joins uitgevoerd moeten worden om de data op te halen uit de verschillende tabellen.
Zowel de revisions als de huidige data (bij mongodb_field_storage) worden opgeslagen in de MongoDB-database. De verschillende elementen die men bij de 'field_sql_storage' kon terugvinden in de verschillende kolommen van de tabel (zoals taal, delta...) zullen als object opgeslagen worden in het document.
In de praktijk zal de MongoDB Field Storage module gebruikt worden in een situatie met veel velden/data.
Er zijn enkele opmerkingen om deze submodule te gebruiken.
De contrib module Views zal standaard queries aanmaken die geschikt zijn voor relationele databanken. Hiervoor zijn er enkele oplossingen:
Er wordt gekozen voor MongoDB bij een grote hoeveelheid aan nodes/velden. In zo'n situatie wordt er vaak gekozen voor de Solr-technologie (Search API). Die technologie zal de nodes met de gekozen velden indexeren, om zo sneller in de data te zoeken. Views kan gebruikmaken van de data die geïndexeerd zijn door Solr.
Zoals we eerder al vertelden, kan er altijd een keuze gemaakt worden om bepaalde velden/content types niet te 'converteren' naar MongoDB, maar om nog steeds de standaard storage_type/storage_module te gebruiken als opslag (field_sql_storage).
Contrib module EFQ Views zal gebruikmaken van EntityFieldQuery als query back-end.
Aangezien MongoDB nog niet veel gebruikt wordt (zo'n vijfhonderd Drupal-websites), zijn er nog wat bugs in deze module.
Calibrate is maintainer van de MongoDB contrib module en we hebben ervoor gezorgd dat MongoDB zal werken met Paragraphs en Field Collections.
Er is altijd kans dat bepaalde (contrib) modules rechtstreeks gebruikmaken van een MySQL-query door middel van db_query. Een gouden tip is om altijd alle nieuwe functionaliteiten te testen bij het gebruik nieuwe contrib modules. Hiermee kan men eventuele problemen sneller oplossen.
Indien je kiest om MongoDB te gebruiken, installeer en configureer je dit best vanaf het begin van je project, zodat men bovenstaande problemen sneller kan opmerken.