Kandidatavhandling i Programvaruteknik 06 2012
Jämförelse av Mysql och MongoDb
Alfred Wester
Olof Fredriksson
Kontaktinformation: Författare: Alfred Wester E-mail: alfredwester@gmail.com Olof Fredriksson E-mail: fredriksson@olof.nu Handledare: Nina D. Fogelström School of ComputingSektionen för datavetenskap och kommunikation
Blekinge Tekniska Högskola Internet : www.bth.se/com
371 79 Karlskrona Phone : +46 455 38 50 00
Abstract. Speed is a very important factor in websites and other types of applications and almost all applications stores some type of data, normally in a database. For an example a blog typically saves users, posts and comments. There’s a high risk that as the amount of data in the database grows, the time for inserting and requesting specific data increases. If it takes more than some seconds to view a specific page, a user will normally leave the site. However, it’s a fact that the database will grow while the application will become more popular but it’s possible to save a lot of time if using right database, and structure. In this thesis MongoDB and MySQL will be compared with focus on time consumption.
SQL (Structured Query Language) is the language which most databases use. This kind of database stores data in structured tables and noting can be added to them if the type of data is incorrect. SQL also support relations between tables. MySQL is a very popular relational database management system (RDBMS) which for example websites frequently makes use of.
NoSQL is a new type of databases where the data is stored in collections without any kind of structure, unlike the well known SQL databases where the data is stored in structured tables. Because of the non-structure, these types of databases are designed to be fast and scalable over multiple machines. Mongodb is a such kind of NoSql-database.
Innehåll
1 Introduktion . . . 5 1.1 Målgrupp . . . 5 2 Bakgrund . . . 5 2.1 Data . . . 5 2.2 MySql . . . 5 2.3 MongoDb . . . 6 2.3.1 Gridfs . . . 7 2.4 Multiinsättning . . . 7 2.5 Json . . . 7 2.6 PHP . . . 73 Forskningsfrågor och metodik . . . 8
3.1 Frågeställningar . . . 8
3.2 Utformining av litteraturstudie . . . 8
4 Resultat från litteraturstudie . . . 8
4.1 Beskrivning av litteratur . . . 9
4.2 Resultat och diskussion . . . 9
4.2.1 RQ1. Vilka jämförelser av Sql och NoSql-databaser finns redan och hur utformades de? 10 4.2.2 RQ2. Vilken databas presterar snabbast när det gäller att sätta in och filtrera data? . . 11
4.2.3 RQ3. Blir det några skillnader på resultatet vid annan uppsättning av miljö? . . . 11
5 Utformining av experiment . . . 12
5.1 Mål. . . 12
5.2 Faktorer . . . 12
5.2.1 PHP . . . 12
5.2.2 Operativsystem & Hårdvara . . . 12
5.2.3 Olika datamodeller . . . 13
5.2.4 Datamängder . . . 13
5.2.5 Vad för typ av data . . . 13
5.2.6 Sätta in all data samtidigt . . . 13
5.3 Testmiljö . . . 13 5.3.1 Systeminformation . . . 14 5.4 Datamodell . . . 14 6 Utförande . . . 14 6.1 Testfall . . . 14 6.2 Insättning . . . 15 6.3 Filtrering . . . 16 7 Resultat . . . 17 7.1 Insättning . . . 17 7.1.1 Ubuntu 64 . . . 17 7.1.2 Ubuntu 32 . . . 18 7.2 Filtrering . . . 18 7.2.1 Ubuntu 64 . . . 18 7.2.2 Ubuntu 32 . . . 19
8 Analys och diskussion . . . 19
8.1 Tester som inte kunde genomföras . . . 19
8.2 Analys av resultatet . . . 20
8.3 Olika sätt att hantera resultatet . . . 20
8.4.1 MongDb är snabbare . . . 20
8.4.2 MongoDb på ett 32-bitars system . . . 21
8.5 Validering av resultat . . . 21
8.6 Kopplingar till tidigare arbeten . . . 21
8.7 Framtida arbete . . . 21
9 Sammanfattning . . . 22
A Datamodeller . . . 26
A.1 MySql - Insättning . . . 26
A.2 MongoDb - Insättning . . . 26
A.3 MySql - Filtrering . . . 27
A.4 MongoDb - Filtrering . . . 28
A.4.1 Med relationer . . . 28
A.4.2 Utan relationer . . . 28
B Källkod . . . 29
C Diagram . . . 39
C.1 Insättning av data Ubuntu 64 . . . 39
C.2 Insättning av data Ubuntu 32 . . . 39
C.3 Filtrering av data Ubuntu 64 . . . 40
1
Introduktion
Dagens populära webbtjänster som till exempel Facebook[1] och Twitter[2] sparar undan en stor mängd data kring användarna och de aktiviteter som görs. Samtidigt som det hela tiden växer med information som ska lagras är det fortfarande en hög prioritet att datan ska gå att ladda snabbt, en fördröjning på endast några sekunder kan resultera till i en förlorad användare som i sin tur kan vara förödande för tjänsten. Det finns idag ett flertal olika databastyper där grundprincipen är samma, att skriva och läsa ut data. Det som däre-mot skiljer dem är deras sätt att hantera datan och hastigheterna att läsa ut från databasen varierar kraftigt. I detta arbete har vi tänkt att testa och jämföra två olika typer av databaser, SQL och NoSql. Vi ska generera ett par tester och mäta vilken av dem som presterar snabbast. Testerna ska, i så stor grad som möjligt, återspegla verkliga scenarion, för att ta reda på hur mycket snabbare MongoDb är istället för MySql och hur strukturen på databasen förändras.
Valet av dessa två är dels för att MySql är en av de populäraste databaserna och som många faktiskt känner till. MongoDb är däremot relativt ny och släpptes 2009 så troligtvis är det inte alls lika många som känner till den. I en tidigare uppsats[3] som skrivits jämförs CouchDb och MongoDb där MongoDb vinner i snabbhet på de flesta testerna vilket gör det ännu mer spännande att göra jämförelser med MySql.
1.1 Målgrupp
Målgruppen för detta arbete riktar sig till alla som är intresserade eller jobbar med olika typer av databaser. Den grundläggande informationen kring respektive typ finns under sektion 2 bakgrund, men vi rekommen-derar ändå att man har några tidigare erfarenheter antingen genom att ha jobbat med databaser eller kan grundprinciperna om hur de fungerar.
2
Bakgrund
2.1 DataData, eller information kan innehålla till exempel uppgifter kring en användare, som namn och lösenord. I vårt fall finns denna information tillgänglig i databaser och hämtas sedan fram med hjälp av anrop. Beroende på hur mycket data man ska hämta hem, och ifall någon filtrering görs så kommer detta ta en viss tid, vilket vi kommer jämföra mellan två de olika typerna.
2.2 MySql
Sql är ett språk som hanterar kommunikationen med en relationsdatabas. Språket utvecklades under 70-talet och idag finns det ett flertal databaser som stödjer Sql. MySql[4] är en av dessa och släpptes redan 1995 av MySql AB. Populäriteten ökade snabbt och idag är det ett vanligt alternativ på både hemsidor och andra typer av applikationer. Kortfattat så är en relationsdatabas uppbyggd med tabeller, fält och poster. Anta att det är en tabell med medlemmar, där fälten är namn och lösenord så kommer varje medlem på en separat rad i tabellen. Sql-kommandot för att hämta ut alla medlemmar och dess information görs med en Select[5] som då blir:
SELECT * FROM members
För att sedan filtrera informationen och bara hämta ut vissa data, används WHERE, LIKE och liknan-de operationer.
kommentarer kan detta sparas i två separata tabeller. Givetvis är det möjligt att spara användarinformatio-nen i tabellen för inläggen, men då utnyttjar man inte styrkan med relationsdatabaser. Det rekommenderade sättet att strukturera det är att i tabellen för inlägg, endast spara ned id-nummret till användaren, och sedan koppla ihop detta till Member där denna information endast behövs sparas ned på en rad. Samma princip gäller tabellen för kommentarer.
Sql-koden för att nu hämta hem alla artiklar som användaren Simba skapat kan nu se ut såhär: SELECT ∗ FROM `Post ` as P INNER JOIN Member as M
ON P. idMember = M. idMember AND M. name = ' Simba '
Figur 1: Exempel på en relationsdatabas för medlemmar, blogginlägg och kommentarer
I relationsdatabaser används nycklar för att koppla ihop tabellerna. Begreppet kallas för främmande nycklar[6] och kan se till så att datan är konsistent. Ett exampel är att det är möjligt att förhindra att en medlem inte går att radera sålänge det finns artiklar kopplade till användaren, nackdelen är att detta kan leda till att databasen blir slöare för att sätta in och proccessera data.
2.3 MongoDb
MongoDb[7] är en slags NoSql-databas som egentligen inte är någon ny teknik, men det är på senare år som det växt otroligt och är idag ett hett ämne när man pratar om stora och skalbara lösningar till sina databaser. Precis som med SQL finns det även flera NoSql-databaser, där de skiljer sig lite från varandra. MongoDb sparar undan informationen i Json-liknande format, BSON. Det är en binär serialisering av Json och är utformat för att vara lättviktigt, enkelt att traversera i samt effektivt[8]. Grunderna kring Json finns i sektion 2.5 Json. Sättet att kommunicera med databasen och hur informationen lagras skiljer sig alltså en hel del i jämförelse med relationsdatabaserna.
Varje objekt som sätts in i databasen kommer få ett unikt id som bland annat baseras på tiden samt process-id[9].
{
" _id ": O b j e c t I d (" 4 f d 2 3 0 2 6 6 8 0 3 f a 9 d 1 0 0 0 0 3 e 7 ") , " title ": " Awesome post ",
" content ": " Lorem ipsum dolor sit amet , c o n s e c t e t u r a d i p i s c i n g elit . [...] ", " tags ": { " 0 ": " dummy post ", " 1 ": " tag ", " 2 ": " Mufasa ", } }
Listing 1: En relationsfri Collection med inlägg och dess taggar 2.3.1 Gridfs
MongoDb har i den senaste versionen (2.0.5) en begränsning på 16MB[10] per objekt och vid insättning av stora filer i databasen kan det därför finnas en risk att filen helt enkelt inte får plats. För att komma runt detta finns GridFs[10] implementerat och skillnaden är att filen automatiskt delas upp i mindre bitar vid behov och begräsningen på en maximal filstorlek försvinner. Det är nu möjligt att spara ned betydligt större filer som till exempel filmer.
2.4 Multiinsättning
För både MySql och MongoDb finns ett alternativt sätt att sätta in data: multi-insert för MySql och bulk-insert[11] för MongoDb. Istället för att sätta in ett element i taget, sätts då alla element in med ett enda kommando. Detta är speciellt användbart när många element ska sättas in på samma gång eftersom data-basen då endast behöver hantera en request.
2.5 Json
JavaScript Object Notation, Json[12] är ett textformat som används till att lagra och skicka data, och har blivit ett alternativ till eXtensible Markup Language, XML. Ett användningsområde där kommunikation med Json används är mellan en server och webbläsare, till exempel om man vill ladda ned innehåll dyna-miskt med hjälp av Javascript.
{ " f ir st Na me ": " John ", " lastName ": " Doe ", " phoneNo ": " +4600012 ", " active ": true }
Listing 2: Ett exempel på hur ett Json-objekt kan se ut
2.6 PHP
3
Forskningsfrågor och metodik
3.1 FrågeställningarArbetet ska försöka att besvara följande frågor:
RQ1. Vilka jämförelser av Sql och NoSql-databaser finns redan och hur utformades de? RQ2. Vilken databas presterar snabbast när det gäller att sätta in och filtrera data? RQ3. Blir det några skillnader på resultatet vid annan uppsättning av miljö? Listan nedan visar vilka metoder respektive fråga kommer att besvaras med: RQ1. Forskning i litteratur
RQ2. Experiment/tester RQ3. Experiment/tester
3.2 Utformining av litteraturstudie
Sökning efter lämplig litteratur genomfördes under ett antal dagar och resulterade i en lista med artiklar av olika slag, men även guider och länkar till givande webbsidor hittades. Resultaten hittades uteslutande på internet med hjälp av följande sökmotorer:
– Google schoolar – BTH Summon – Google
De söktermer som användes var: – Nosql
– nosql, mysql vs nosql
– Comparison between NoSQL and mysql – paper nosql mysql
– nosql performance – mysql performance
– mysql nosql php perspective – prestandaskillnader nosql mysql
De kriterier som fanns för att godkänna en artikel var att den måste vara publicerad senare än 2008 och att artikeln ska innehålla något som rör någon av databastyperna. Anledningen till att de inte ska vara äldre än från 2008 beror på att även om Nosql funnits länge, är det de senaste åren som det blivit ett väldigt hett ämne och blivit ett alternativ för tjänster med stora mängder data. Äldre artiklar kan även innehålla irrelevanta saker, till exempel funktionalitet som då inte fanns tillgänglig men gör det nu.
4
Resultat från litteraturstudie
4.1 Beskrivning av litteratur
Tabell 1 visar artiklarna från litteraturstudien där blått symboliserar arbeten skrivna av studenter(33%), grönt är papper som publicerats i konferenser(42%) och de som är markerade med orange är övriga artiklar såsom guider eller artiklar publicerade på internet(25%).
Det som är gemensamt för alla artiklar är att de handlar om MySql, NoSql eller något som relaterar till dem. Vi har försökt finna och välja ut de som antingen handlar om prestanda eller de som jämför databasty-perna på något sätt och som inte är utgivna tidigare än 2008. Som sökmetod för att hitta artiklar användes internet, genom de sökmotorer som nämnts i sektion 3.2. Den funna artikelns sammanfatting låg till grund för att avgöra om den var relevant eller inte.
Artikel Rubrik Ref.
P1 Document Oriented NoSQL Databases - A comparison of performance in MongoDB and CouchDB using a Python interface
[3]
P2 Utredning av NoSQL-databaser för Sogeti i Gävle [15]
P3 Data modeling with NoSQL: how, when and why [16]
P4 Building blocks of a scalable web crawler [17]
P5 Will NoSQL databases live up to their promise? [18]
P6 Debunking the NoSQL Hype [19]
P7 Security Issues in NoSQL Databases [20]
P8 Using MongoDB to Implement Textbook Management System instead of MySQL [21] P9 MySQL Performance Analysis on a Limited Resource Server: Fedora vs. Ubuntu Linux [22]
P10 MySQL & NoSQL from a PHP Perspective [23]
P11 Getting Started with MongoDB and PHP [24]
P12 Schema-Free MySQL vs NoSQL [25]
Tabell 1: Funna artiklar i litteraturstudie
4.2 Resultat och diskussion
Fråga Relaterade artiklar
RQ1. P1[3], P2[15], P4[17], P5[18], P8[21], P12[25] RQ2. P1[3], P2[15], P8[21]
RQ3. P2[15], P9[22]
Tabell 2: Artiklar relaterade till forskningsfrågor
4.2.1 RQ1. Vilka jämförelser av Sql och NoSql-databaser finns redan och hur utformades de?
Tabell 2 visar att det finns ganska många artiklar som på något sätt jämför Sql med NoSql. De flesta ar-tiklar som jämför databaser handlar om samma databastyp, dvs NoSql vs NoSql eller SQL vs SQL. I de flesta av de artiklar som hittats ligger inte fokus på själva jämförelsen mellan SQL och NoSql men den är oftast nödvändig för att ge läsaren tillräkligt med bakgrundskunskap om skillnaderna mellan dem. I sådana artiklar görs heller inga detaljerade experiment mellan databastyperna utan jämförelsen består mestadels av ren fakta. Henricsson[3] jämför de två NoSql-databaserna MongoDb och CouchDB och för att göra det krävs att läsaren har viss kunskap kring både NoSql och Sql. Därför ges detta som bakgrund innan experimenten genomförs.
Söderberg och Eriksson[15] utför inte heller några experiment när det gäller jämförelse av Sql och NoSql. Arbetet är främst utformat som en litteraturgranskning där de tar upp skillnader mellan NoSql-databaser men även mellan NoSql och Sql. De tar upp för och nackdelar för de olika databaserna och diskuterar vilka användningsområden som lämpar sig för respektive typ. Arbetet innehåller även information om skalbarhet mellan de olika databaserna, detta är dock inte något som detta arbete kommer att lägga fokus på. MySql’s styrka med relationer skapar en svaghet för bland annat webbapplikationer, där hög prioritet är att man kan hämta ned data snabbt ur databasen. Till detta ändamål kan en NoSql-databas vara mer lämpligt att använda. I vårt arbete är det viktigt att testerna inte är “partiska” till en viss databastyp.
Syftet med Seegers[17] arbete är att bygga en skalbar sökrobot för webben. För att kunna implemente-ra en sådan genomförs först en omfattande utvärdering av olika verktyg och även en mängd olika databaser. Bland dem finns både MongoDb och MySql, men det görs ingen direkt jämförelse mellan dem. Denna ut-värdering kan vara mycket relevant för vårt arbete. Alla utut-värderingar bygger på fakta ifrån andra studier som sedan ligger till grund för valet av de verktyg som ska användas för sökroboten. Segeer kommer fram till att MongoDb inte kan användas eftersom molnmiljön där applikationen är tänkt att köras använder ett 32-bitars operativsystem. MongoDb har nämligen en storleksbegränsning på 2Gb i ett 32-bitars system[26]. För att bygga sökroboten används istället MySql som databas. Detta är för att MySql lätt kan integreras mot andra system som är nödvändiga. Detta arbete kommer att utföra experiment med MongoDb på både 32 och 64-bitars os för att se vad skilladerna blir.
Artikel P5 är skriven av Neal Leavitt[18] och är utformad som en tidningsartikel. Inte heller denna arti-kel utför några experiment. Istället används intervjuer men även fakta och historia som huvudsakliga källor. Leavitt tar upp för och nackdelar med både Sql och NoSql-databaser. Sql-databaser kan bli långsamma om de använder komplex tabellstruktur och att använda sql där datatyper kan variera, är inte lämpligt eftersom sql är utformat för att användas med strukturerad data. Leavitt kommer fram till att NoSql-databaser inte kan ersätta relationsdatabaser men är ett bra alternativ för vissa typer av projekt, till exempel när skalbar-het är viktigt för databasen. Skalbarskalbar-het kommer inte att testas i vårt arbete.
med MongoDb i ett system för att hantera böcker[21]. Det är dock ett relativt litet arbete som utför tester för insättning och filtrering med en datamodell för MongoDb som har relationer likt modellen för MySql. Därmed missar de en del av poängen med NoSql-databaser som inte behöver använda relationer för att på så sätt öka snabbheten. De båda databaserna sätts upp med tabeller/samlingar med likvärdig data, sedan testas prestanda genom att sätta in 100000 element och filtrera ut 2000 element av dessa. Exemplet på hur MongoDB kan ersätta MySQL är relevant för våra tester så att resultaten kan jämföras.
Grigorik[25] visar att det går att använda MySql på liknande sätt som NoSql-databaser, d.v.s. utan för-definierad struktur. Detta är en intressant synvinkel som inte stötts på i någon tidigare artikel. Han menar att MySql har en väldig styrka med relationer, speciellt med databasmotorn InnoDB. Genom att använda MySql-databasen utan schema bevaras denna stryka samtidigt som den inte bryr sig om strukturen för de element som ska sättas in, likt NoSql.
4.2.2 RQ2. Vilken databas presterar snabbast när det gäller att sätta in och filtrera data? Fråga två kommer dels att besvaras genom de experiment som genomförs men litteraturen är också en viktig del för att förklara resultatet och eventuella skillnader samt att kunna stukturera upp detta arbetes experi-ment.
Henricsson[3] utför tester mellan de två databaserna CouchDb och MongoDb. För att ge MySql en vär-dig motståndare, är detta ett bra arbete för att hitta en snabb databas av typen NoSql. De tester som genomförts är insättning av data samt filtrering av olika slag. Testerna liknar, till stor del, de som kommer att genomföras i vårt arbete och ger därför en hel del relevant information hur experiment för databaser kan genomföras. Resultatet från Henricssons arbete visar att MongoDb var betydligt snabbare och vann i stort sett alla tester som genomfördes. Utifrån detta resultat har vi valt just MongoDb som motståndare till MySql. I den litteraturgranskning som Söderberg och Eriksson[15] genomfört vägs de bägge koncepten, NoSql och Sql, mot varandra ur olika perspektiv. Eftersom inga tester genomförs i arbetet går det inte rikitgt att avgöra vilken av databaserna som prestarar snabbast. De säger dock att NoSql är snabbare, speciellt vid filtrering. Eftersom vårt arbete kommer genomföra tester för detta kan vi kanske ge svar på om detta stämmer eller inte. En anledning till att NoSql är snabbare är att datamodellerna oftast är mycket simplare. De har även med lite benchmarking om prestanda där de bl.a. säger att Cassandra kan skriva till ett datalager som tar upp 50 GB på disken på 0,12 millisekunder, mer än 2 500 gånger snabbare än MySQL. Med detta som grund kan vi då fråga: är även MongoDb snabbare än MySql?
Wei-ping m.fl[21] kommer fram till att MongoDb är snabbare än MySql, även om testerna använder re-lationer. Detta visar att relationer i MongDb kanske kan vara bra att använda där det behövs. Arbetet är det enda vi hittat som jämför just MySql och MongoDb, dessutom är det ganska litet. I vårt arbete kommer vi genomföra fler tester och även testa MongoDb utan att använda relationer, för att se om det blir några uppenbara skillnader.
4.2.3 RQ3. Blir det några skillnader på resultatet vid annan uppsättning av miljö?
Precis som tidigare fråga så kommer fråga tre att besvaras med hjälp av experiment, men även att studera de artiklar som handlar om prestanda (se relaterade artiklar i tabell 2).
enklare att skala en NoSql-databas över flera datorer istället för att lägga pengar på en enda dator med extrem hårdvara. Självklart påverkas resultatet av vilken hårdvara som används. För att visa det kommer vi även att utföra alla tester på olika datorer, med olika hårdvara och opertivsystem.
Experimenten i artikel P9[22] testar prestanda i MySql och utfördes som en klient-server applikation. Tes-terna gick ut på att använda transaktioner för att utföra operationer med 10000, 50000 och 100000 rader i tabellerna. Under tiden mättes prestanda i TPS(Transactions Per Second). För varje test ökade de antalet trådar att använda för att på så sätt utreda hur stor påverkan det har på resultaten. De slutatser man kan dra utifrån arbetet är att val av operativsystem och inställningar påverkar prestandan mycket. MySql server presterar snabbare på Ubuntu 8.04 än Fedora 8 i de flesta situationer. Antalet trådar som används har stor inverkan på cpu och minnesanvändning. Resultaten kan vara värdefulla när vi utvärderar prestandaskillnader mellan MySQL och NoSQL.
5
Utformining av experiment
5.1 Mål
Målet med de experiment som ska genomföras är att ta reda på vilken databas som snabbast sätter in data samt filtrerar data. Givetvis täcker inte de definierade testerna alla olika scenarion som finns men kommer fortfarande att ge en bra bild över hastighetsskillnaderna mellan databaserna. Testerna kommer även att testas på två datorer för att se om ytterligare skillnader uppstår vid olika uppsättningar av miljö.
5.2 Faktorer
Nedan följer faktorer som kan påverka resultetet av experimenten och hur de hanteras.
5.2.1 PHP
Varje databas har sina egna funktioner för att beräkna tid för olika operationer. För att minimera risken att de mätningar som ska utföras blir till fördel för en viss databas har vi tagit beslutet att inte använda dessa funktioner. Istället kommer vi använda unix-kommandot time, men då krävs att experimenten kan köras som ett kommando ifrån en unixterminal där man undviker steget att först starta databasens administra-tionsgränssnitt. För att lösa detta problem kommer php att användas som scriptspråk. Därmed medförs också faktorn att scriptet i sig använder en viss tid, vilket i sin tur gör att databasens tid inte blir exakt. Att tillverka scriptet så att det inte använder någon tid alls är helt omöjligt. Därför kommer php-scriptet att göras så litet som möjligt och vi kommer att se till att scriptets tid varierar minimalt från gång till gång. Vi kommer även att köra varje test 5 gånger och sedan räkna ut medelvärdet för varje testfall och på så vis minimera scriptets påverkan på resultatet.
5.2.2 Operativsystem & Hårdvara
5.2.3 Olika datamodeller
Eftersom MySql är en relationsdatabas och MongoDb är en NoSql-databas utan relationer, finns risken att resultaten kan bli felaktiga och orättvisa eftersom datamodellen kommer att se olika ut för respektive da-tabas. MongoDb har dock ett sätt att hantera relationer, där man istället för att spara själva värdet i en array i objektet, sparar en referens till ett annat objekt i databasen i en likvärdig array. Eftersom dessa två varianter finns att bygga upp datamodeller på i MongoDb, kommer även relations-varianten att testas i detta arbete.
Exerimenten kommer innehålla att spara ned bilder i databaser, och MongoDb innehåller ett speciellt system för att spara ned filer som kallas för gridFs, och finns beskrivet i sektion GridFs 2.3.1. Tester kommer därför att genomföras både med och utan gridFs för att se ifall det har någon större påverkan.
5.2.4 Datamängder
En annan faktor som kan påverka resultatet vid insert är om databasen redan innehåller data när testerna körs. Det kan t.ex. vara så att det tar längre tid för databasen att sätta in ett nytt element om databasen inte är tom. Detta arbete kommer inte att utföra några experiment som tar hänsyn till denna faktor. Vi anser att påverkan är minimal och därför kommer denna typ av tester endast att utföras på tomma databaser. 5.2.5 Vad för typ av data
Insättning av olika typer av data kan påverka tiden, och för att ta reda på skillnader det kommer tester att genomföras där både databasen får lagra nummer, strängar samt bilder i binär form.
5.2.6 Sätta in all data samtidigt
Både MySql och MongoDb har stöd för att sätta in all data i en enda förfrågning, istället för att göra en förfrågning per objekt som ska läggas till. Experiment kommer utföras både med och utan detta och se eventuella skillnader både mellan typerna och inom samma databas.
5.3 Testmiljö
Genereringen av testdatan kommer att skötas från en ny funktion i ett php-skript och den data som kommer att skapas finns definierad under sektionen Datamodell 5.4. Givetvis kommer detta att påverka den slutgiltiga tiden för exekveringen, men då båda databaserna kommer att få denna extratid, kan den ignoreras vid jäm-förelse av resultatet. För att alltid samma data ska genereras, har vi statiskt angett ett specifikt srand-värde. För att mäta tiderna kommer Unix-kommandot time att användas. Anledningen till att använda detta istället för tiden som man direkt kan få ut från MySql och MongoDb, är att vi vill kunna använda samma tidsfunktion till båda databas-typerna. Detta för att minimera felmarginaler för tiden man kan få fram från respektive databas, då vi inte kan säkerställa att tiden räknas ut på exakt samma sätt. Varje enskild mätning kommer att göras fem gånger, och sedan kommer medelvärdet att räknas ut.
Real: Den faktiskta tiden det tar att exekvera ett kommando, som att använda ett stoppur. User: Visar CPU-tiden, spenderad i "user mode".
Sys: Visar tiden, spenderad i kärnan, "Kernel".
5.3.1 Systeminformation
Mjukvaran är densamma för båda datorerna förutom operativsystemet: PHP: 5.3.5
MySql: 5.1.62 MongoDb: 2.0.5 Dator 1:
Operativsystem: Ubuntu GNU/Linux 11.04 64 bit Processor: AMD Dual Core 3GHz
Minne: 4 GB Dator 2:
Operativsystem: Ubuntu GNU/Linux 11.04 32 bit Processor: Intel Core 2 Duo 2.67GHz
Minne: 2 GB 5.4 Datamodell
Datamodellerna skiljer sig åt mellan de experiment som ska göras. För insättning kommer det finns två olika tabeller, en för Medlemmar där strängar kommer sparas, samt en bild-tabell där bilder i binär form lagras. MongoDb kommer även testas med gridFs som finns beskrivet under sektion GridFs 2.3.1. Vid testerna för filtrering kommer Mysql ha tabeller för produkter och kategorier, vilket skapar ett många till många-förhållande. Även här kommer MongoDb innehålla två olika lösningar, en helt fri från relationer med endast en tabell och en annan variant med två tabeller. Tabeller med en överblick hur databasmodellen ser ut både för insättning och filtrering finns i bilaga A.
6
Utförande
RQ2 och RQ3 kommer att besvaras genom experiment. Två datorer med olika hårdvara och operativsystem har satts upp för att kunna genomföra tester med både MySql och MongoDb. Under sektion 5.3.1 Syste-minformation, specificeras hårdvaran samt operativsystem som kommer att användas för respektive dator. Databaserna kommer att testas med hjälp av ett php-skript. Kommandot för att exekvera php-sriptet som gör en insättning på 10000 rader i MySql ser ut såhär:
time php insertMySql.php -n 10000 -t i
6.1 Testfall
6.2 Insättning
Tabell 3 visar testfallen för instättning där två olika datatyper kommer att användas: Member och Image (För mer inormation om datamodellerna se bilaga A.1 och A.2). Experiment kommer också att utföras med multiinsättning (sektion 2.4 Multiinsättning) för 100 000 members och fler. Anledningen till att färre antal inte kommer att testas med detta är att det handlar om så små mängder så multiinsättning inte anses relevant. Kolumnen “antal” anger hur många element som ska sättas in för varje test.
TestId Dator Datatyp Multiinsättning Antal
1 Ubuntu 64 Member nej 1000
2 Ubuntu 64 Image nej 1000
3 Ubuntu 64 Member nej 10 000
4 Ubuntu 64 Image nej 10 000
5 Ubuntu 64 Member nej 100 000
6 Ubuntu 64 Member ja 100 000
7 Ubuntu 64 Member nej 1 000 000
8 Ubuntu 64 Member ja 1 000 000
9 Ubuntu 32 Member nej 1000
10 Ubuntu 32 Image nej 1000
11 Ubuntu 32 Member nej 10 000
12 Ubuntu 32 Image nej 10 000
13 Ubuntu 32 Member nej 100 000
14 Ubuntu 32 Member ja 100 000
15 Ubuntu 32 Member nej 1 000 000
16 Ubuntu 32 Member ja 1 000 000
6.3 Filtrering
Tabell 4 visar alla testfall som ska köras för filtering. I dessa tester ska används datamodellerna för produkt och kategori som finns beskrivna i bilaga A.3 och A.4. I dessa tester ska alla produkter med en viss kategori filtreras ut. För MongoDb finns två sätt att hantera modellen, antingen med relation till en annan collection, eller att all data finns i en array direkt hos objektet. Tester kommer därför att utföras för båda varianterna. Kolumnen “antal” i tabellen nedan visar hur många element som finns i databasen, som därmed behöver sökas igenom för varje test.
TestId Dator Antal
17 Ubuntu 64 1000 18 Ubuntu 64 10 000 19 Ubuntu 64 100 000 20 Ubuntu 64 1 000 000 21 Ubuntu 64 4 000 000 22 Ubuntu 32 1000 23 Ubuntu 32 10 000 24 Ubuntu 32 100 000 25 Ubuntu 32 1 000 000 26 Ubuntu 32 4 000 000
7
Resultat
Nedan presenteras resultat från alla tester som genomförts. De tester som är rödmarkerade är sådana som av någon anledning inte kunde fullföljas. De tider som är skrivna med grön text visar den snabbaste tiden för testet. Varje test kördes fem gånger där tiden mättes varje gång, sedan räknades medelvärdet av dessa tider ut och det är den tiden som visas i tabellerna nedan. Alla tider är angivna i sekunder.
7.1 Insättning
Tabell 5 och 6 visar resultat för insättning av medlemmar och bilder på de olika datorerna. Kolumnen “Antal” anger hur många element som sattes in i databasen vid respektive test. Vid insättning av bilder genomfördes ett ytterligare test med GridFs för att se om det blev några skillnader. Tabellen visar att användandet av GridFs gjorde att tiden ökade med några sekunder. MongoDb visade sig vara snabbare på de flesta testerna förutom de som använde multiinsättning (sektion 2.4 Multiinsättning). Test nummer 8 och 16 kunde inte genomföras för MongoDb på grund av det finns en 16mb-spärr för objektens storlek. Denna spärr kunde inte heller konfigureras.
7.1.1 Ubuntu 64
TestId Datatyp Antal Multi MySql MongoDb GridFs
1 Member 1000 nej 0,146 0,122 2 Image 1000 nej 3,859 1,353 3,385 3 Member 10 000 nej 0,712 0,310 4 Image 10 000 nej 43,515 50,170 53,603 5 Member 100 000 nej 7,214 3,157 6 Member 100 000 ja 0,874 2,388 7 Member 1 000 000 nej 65,868 34,687 8 Member 1 000 000 ja 7,120 0
7.1.2 Ubuntu 32
Testerna med GridFs för bilder kunde inte slutföras på grund av storleksbegränsningen för lagring i MongoDb på 2Gb på ett 32-bitarssystem.
TestId Datatyp Antal Multi MySql MongoDb GridFs
9 Member 1000 nej 0,079 0,048 10 Image 1000 nej 4,693 0,788 0 11 Member 10 000 nej 0,479 0,299 12 Image 10 000 nej 47,207 18,327 0 13 Member 100 000 nej 4,432 1,720 14 Member 100 000 ja 0,544 1,763 15 Member 1 000 000 nej 43,965 17,745 16 Member 1 000 000 ja 5,138 0
Tabell 6: Resultat för testerna med insättning på Ubuntu 32 7.2 Filtrering
Tabell 7 och 8 visar resultat från experimenten med filtrering av data. Kolumnen “Antal” anger hur många element som fanns i databasen när testen utfördes och som därmed filtrerades. Eftersom det finns två varianter på att hantera datamodellen i MongoDb testades båda två. Kolumnen “MongoDb Relationer” visar resultaten från testerna med separata collections för relationer mellan produkt och kategori. Kolumnen “MongoDb” visar resultaten från testerna utan relationer. Även här visade det sig att MongoDb är snabbare än MySql och att använda MongoDb utan relationer är snabbast.
7.2.1 Ubuntu 64
TestId Antal MySql MongoDb Relationer MongoDb
17 1000 0,085 0,081 0,076
18 10 000 0,136 0,135 0,120
19 100 000 0,486 0,457 0,416
20 1 00 000 20,616 3,009 2,344
21 4 000 000 82,427 11,826 8,546
7.2.2 Ubuntu 32
TestId Antal MySql MongoDb Relationer MongoDb
22 1000 0,040 0,036 0,036
23 10 000 0,080 0,051 0,049
24 100 000 0,500 0,208 0,181
25 1 000 000 23,490 1,874 1,600
26 4 000 000 96,136 16,061 14,898
Tabell 8: Resultat för filtrering med insättning på Ubuntu 32
8
Analys och diskussion
Experimentresultaten är väldigt intressanta, de flesta var väntade, men vid insättning var faktiskt MySql snabbare än MongoDb när multi-insert användes. Graferna nedan visar hur resultatet påverkades av antalet element som sätts in eller filtreras. Fler diagram och större format finns i bilaga C.
8.1 Tester som inte kunde genomföras
Tabellerna visar att det var några experiment som inte gick att fullfölja. Anledningen till att test 8 och 16 fal-lerade på MongoDb är att det finns en gräns för objektens storlek på 16mb. Dokumentationen för MongoDb säger att denna begränsning gäller på de enskilda objekten som sparas i databasen. Så verkar dock inte vara fallet utan beräkningen görs på den data som faktiskt skickas till socketen. Detta bekräftas i ett ärende[27] som finns publicerat på Github där MongoDb’s kod finns uppladdad. Experimentet som genomfördes i detta arbete, skulle sätta in ett visst antal element som en så kallad bulk-insert. Vilket betyder att alla element skickas till databasen i en enda request som MongoDb sedan hanterar och lagrar som många objekt. Två dagar innan testen genomfördes släpptes en fix för detta problem men den php-driver som detta arbete använder sig av, verkar inte ha lagt in stöd för detta ännu. Även MySql har en gräns på 16mb men denna kan lätt utökas via en konfigurationsfil, vilket gjordes för experimentet.
De två andra testerna som inte kunde genomföras var insättning av bilder i gridFs på datorn med Ubuntu 32. Alla de tidigare testerna hade slutförts men när dessa skulle köras, uppstod fel som:
MongoDb : can ' t map f i l e memory − mongo r e q u i r e s 64 b i t build f o r l a r g e r d a t a s e t s
8.2 Analys av resultatet 0 10 20 30 40 50 60 70 1000 10000 100000 10000000 Tid(s) Antal MySql MongoDb
Figur 2: Ubuntu 64, Insättning av data Figur 2 visar tidsskillnaderna mellan MySql och
MongdoDb vid insättning. Diagrammet visar tyd-ligt att MySql tar längre tid på sig än sin konkur-rent, speciellt vid insättningen av det högsta an-talet element som var 1000000st. MongoDb sätter in medlemmarna på drygt 35 sekunder där Mysql gör det på 66 vilket anses som en betydlig ök-ning.
Det är emellertid inte vanligt att databasen behö-ver hantera denna typ av insättning med så mycket samtidig data. Resultatet för insättning av, upp till drygt tiotusen members, ligger på mindre än en se-kund för båda databaserna vilket inte anses speciellt mycket.
Det som däremot går snabbare för MySql är om insättningen sker i en så kallad multiinsert(bulk-insert för MongoDb) där all data sätts in med ett anrop. MongoDb klarade inte ens av att genomföra båda tester-na på grund av den gräns som finns för objekten. Resultaten för 32-bitarsdatorn visar liktester-nande värden, med samma mönster där MySql tar betydligt längre tid på sig att sätta in större mängder data.
0 10 20 30 40 50 60 70 80 90 1000 10000 100000 10000000 40000000 Tid(s) Antal MySql MongoDb utan relationer MongoDb med relationer
Figur 3: Ubuntu 64 : Filtrering av data Även om det inte är vanligt att sätta in större
mäng-der data på en gång, så är det tvärt om när det gäller hämtning och filtrering av information. Den struktur för tabeller/collections som användes under experi-mentet var relativt enkel, men ändå kan man se att MongoDb är betydligt snabbare än MySql.
Vid filtrering av 4 miljoner produkter skiljer det un-gefär 70 sekunder, vilket är en enorm skillnad. Skill-naderna mellan MongoDb med och utan relationer är märkbar, men i detta fallet inte speciellt kritisk, på 4 miljoner data skiljer det sig cirka 3 sekunder vil-ket inte anses speciellt mycvil-ket i jämförelse till Mysql. 8.3 Olika sätt att hantera resultatet
MySql och MongoDb skiljer sig på många punkter,
bland annat hur de hanterar resultatet som skickas ned till klienten, i detta fall till php-scriptet som hanterar testerna. Det som händer när en sökning görs i MongoDb är att data inte skickas ned direkt till applikationen, istället skickas en pekare till resultatet. Fördelen är att klienten då slipper att spara all information i minnet och kan istället hantera varje enskilt dokument, ett i taget, när så önskas. MySql däremot skickar hela resultatet på en gång, vilket kan bli väldigt dyrt för minnet om det handlar om större mängder data. 8.4 Slutsatser
8.4.1 MongDb är snabbare
endast på 4 miljoner vilket kan ses som väldigt lite i jämförelse till Facebook[1] som i april detta året hade över 900 miljoner aktiva användare[28]. Att göra experiment på sådan stor mängd data skulle med stor sannolikhet styrka argumenten till att använda MongoDb istället för MySql.
8.4.2 MongoDb på ett 32-bitars system
Begränsningarna att köra MongoDb på ett 32-bitarssystem nämns kortfattat på MongoDb’s officiella hemsida[26]. De experiment som genomförts i detta arbete kan bekräfta att databasen inte bör användas på ett 32-bitars system. Databasen kraschade även om testerna höll sig inom gränserna och det finns egentligen inga garantier att det går att reparera eventuella fel som uppstår, så att datan kan återställas och fortfarande användas. Det finns många forum på internet med inlägg av personer som har haft liknande problem och den enda egentliga lösningen som de kommit fram till är att köra MongoDb på ett 64-bitarssystem.
8.5 Validering av resultat
Experimenten har inte körts i något realtidssystem och de tider som presenteras i tabellerna är ett medel-värde från fem körningar. Varje test körs aldrig exakt på lika lång tid utan det varierar från gång till gång. Här är det många faktorer som spelar in, till exempel den nuvarande belastningen på datorn. Även den php-kod som använts för att kommunicera med databaserna påverkar sluttiden då det alltid finns småsaker som aldrig går exakt lika fort. Detta uppstår för de båda databasernas tester och på så sätt är det ingen direkt fara att detta inträffar, det är fortfarande möjligt att jämföraMongoDb och MySql.
Resultaten mellan de olika datorerna kan vara missvisande då tiderna var allt för lika på de allra flesta experimenten. Det fanns ett antagande att dator två skulle genomföra testerna långsammare med tanke på halverat ram-minne, men troligtvis jämnade det ut sig med processorn som den hade och fick istället något snabbare resultat än den första datorn. Rent hårdvarumässigt vore det klokare att ha större skillnader på hårdvaran, för att kunna dra några slutsatser.
8.6 Kopplingar till tidigare arbeten
Litteraturstudien visar att intresset för NoSql-databaser är stort, dock visade det sig att rena jämförelser mellan SQL och NoSql inte förekom speciellt ofta. Anledningen till detta är antagligen att NoSql fortfarande är ett relativt nytt begrepp i databasvärden. Det märktes också i de tester som utfördes, att MongoDb inte är lika pålitiligt som MySql, vilket kan bero på att MongoDb är så pass nytt.
Resultaten i detta arbete kan bekräfta ett tidigare arbete som visar att MongoDb är snabbare än MySql[21], åtminstone i de fall som dessa experimenten täcker. Det stärker även påståenden om att NoSql-databaser generellt är snabbare än relationsdatabaser[18]. Detta arbete har dock inte alls fokuserat på säkerhet i data-baserna, men det finns svagheter i NoSql som är viktiga att ta i beaktning[20]. Oracle publicerade en artikel som vi trodde skulle ta upp och diskutera nackdelar med NoSql[19]. Det visade sig dock att artikeln mest handlade om att lyfta upp fördelar med Oracles lösningar och inte så mycket om generella brister med NoSql. 8.7 Framtida arbete
60 dagar så finns totalt 300000 raders historik. Ett testfall skulle då kunna vara att lista alla produkter med dess kategorier och det senaste priset, eller visa prisutveckling för produkterna den senaste månaden. Tiden borde, rent teoretiskt sett, öka drastiskt.
Figur 4: Exempel hur en relation mellan produkter, kategorier och pris kan se ut.
Det hade även varit intressant att göra ytterligare tester mellan olika datorer, men då med större skillnader på hårdvara än de system som detta arbete använt sig av. Att det inte rekommenderas att köra ett 32-bitars system för MongoDb är ett faktum, som även de tester som genomförts i detta arbete kan bekräfta. Det vore därför bättre om man använder 64-bitar på alla de system som ska jämföras. Mer fokus bör läggas på den faktiska hårdvaran och inte bara ta hänsyn till hur mycket minne utan även hastigheten på dem. Förutom ram och processor bör även hastighet och vilket filsystem som håddiskarna använder sig av, tas hänsyn till. Ett annat experiment skulle kunna vara att testa databaserna på 32 vs 64-bitarssystem som har exakt samma hårdvara för att på så sätt redogöra alla skillnader som enbart beror på denna faktor. Dock lämpar sig detta inte för stora mängder data eftersom MongoDb då inte kan testas fullt ut.
9
Sammanfattning
I de fallen som detta arbetet täcker visar att vid byte från MySql till MongoDb är det möjligt att få en betydligt snabbare databas, med en relativt lik struktur. Tiden för filtrering av 4 miljoner produkter för Ubuntu 64 (tabell 7) skiljer sig drygt 70 sekunder mellan databaserna och sedan är den helt relationsfria lösningen för MongoDb några sekunder snabbare.
Testerna visar dock att skillnaderna mellan lösningen med och utan relationer för MongoDb inte är nämnvärt stor så i detta fallet vinner man nog mer att köra alternativet med relationer, då det till exempel räcker att byta kategori-namn på ett ställe istället för på varje enskild produkt tack vare kopplingen med id-nummer. Det är dessutom väldigt lätt att komma igång med MongoDb, precis som för Mysql finns det stöd till de allra flesta populära programspråken[29].
en av idéerna med en icke relationsdatabas. Det kan finnas de fall då det är nödvändigt att använda sig av bland annat främmande nycklar för att säkerhetsställa att databasen är konsistent, och då är det fortfarande MySql som bör användas.
Referenser
1. Facebook.http://facebook.com. 2. Twitter.
http://twitter.com.
3. Robin Henricsson. Document Oriented NoSQL Databases - A comparison of performance in MongoDB and CouchDB using a Python interface.
http://www.bth.se/fou/cuppsats.nsf/all/32737dee280f07ddc12578b200454a24/$file/ BTH2011Henricsson.pdf, 2011.
4. Oracle Corporation. http://www.mysql.com/.
5. Oracle Corporation. SELECT Syntax.
http://dev.mysql.com/doc/refman/5.6/en/select.html. 6. Oracle Corporation. FOREIGN KEY Constraints.
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html. 7. 10gen, MongoDb. MongoDb.
http://www.mongodb.org/. 8. Bsonspec.org. Bson.
http://bsonspec.org/. 9. 10gen, MongoDb. Object IDs.
http://www.mongodb.org/display/DOCS/Object+IDs. 10. 10gen, MongoDb. GridFs.
http://www.mongodb.org/display/DOCS/GridFS. 11. 10gen, MongoDb. Bulk inserts.
http://www.mongodb.org/display/DOCS/Inserting#Inserting-Bulkinserts.
12. D. Crockford. The application/json Media Type for JavaScript Object Notation (JSON). http://www.ietf.org/rfc/rfc4627.txt, 2006.
13. The PHP group. http://php.net.
14. The PHP group. Using PHP from the command line. http://php.net/manual/en/features.commandline.php.
15. Natalja Söderberg/Jan Eriksson. Utredning av NoSQL-databaser för Sogeti i Gävle. http://juseknew.episerverhotell.net/upload/PDF/diverse/NoSQLdatabaser.pdf, 2010.
16. Carlos André Reis Fernandes Oliveira da Silva. Data Modeling with NoSQL: How, When and Why. http://repositorio-aberto.up.pt/bitstream/10216/61586/1/000148158.pdf, 2011.
17. Marc Seeger. Building blocks of a scalable webcrawler.
http://blog.marc-seeger.de/assets/papers/thesis_seeger-building_blocks_of_a_scalable_ webcrawler.pdf, 2010.
18. Neal Leavitt. Will NoSQL databases live up to their promise? 2010. http://www.leavcom.com/pdf/NoSQL.pdf.
19. Alan Downing. Debunking the NoSQL Hype. 2011.
http://ftp-developpez.com/gordon-fowler/Debunking%20the%20NoSQL%20Hype%20Oracle.pdf.
20. Lior Okman, Nurit Gal-Oz, Yaron Gonen, Ehud Gudes, Jenny Abramov. Security Issues in NoSQL Databases. 2011 IEEE 10th International Conference on Trust, Security and Privacy in Computing and Communications (TrustCom 2011), 2011.
21. Zhu Wei-ping, Li Ming-xin, Chen Huan. Using MongoDB to implement textbook management system instead of MySQL. 2011 IEEE 3rd International Conference on Communication Software and Networks (ICCSN 2011), 2011.
22. Mohiuddin Ahmed, Mohammad Moshee Uddin, Md. Saiful Azad, Shariq Haseeb. MySQL performance analysis on a limited resource server: Fedora vs. Ubuntu Linux. SpringSim ’10 Proceedings of the 2010 Spring Simulation Multiconference, 2010.
23. Tim Juravich. MySQL & NoSQL from a PHP perspective.
http://www.slideshare.net/timjuravich/mysql-nosql-from-a-php-perspective, 2011. 24. Vikram Vaswani. Getting Started with MongoDB and PHP.
25. Ilya Grigorik. Schema-Free MySQL vs NoSQL.
http://www.igvita.com/2010/03/01/schema-free-mysql-vs-nosql/, 2010. 26. 10gen, MongoDb. 32 bit limitations.
http://blog.mongodb.org/post/137788967/32-bit-limitations. 27. Github. maxBsonSize checked on command, not individual documents.
https://github.com/mongodb/node-mongodb-native/issues/609.
28. Mark Hachman. Facebook Now Totals 901 Million Users, Profits Slip. 2012. http://www.pcmag.com/article2/0,2817,2403410,00.asp.
29. 10gen, MongoDb. Drivers.
A
Datamodeller
A.1 MySql - InsättningMember
Fält Typ Värdemängd
firstName Varchar(15) En Sträng mellan 2 och 12 tecken
lastName Varchar(15) En Sträng mellan 2 och 12 tecken
username Varchar(15) En Sträng mellan 2 och 12 tecken
age Int 10-99
Image
Fält Typ Värdemängd
id Int 1 till MAX id
image MediumBlob Bild i binär form
A.2 MongoDb - Insättning
Member
Fält Typ Värdemängd
firstName Sträng En Sträng mellan 2 och 12 tecken
lastName Sträng En Sträng mellan 2 och 12 tecken
username Sträng En Sträng mellan 2 och 12 tecken
age Int 10-99
Image
Fält Typ Värdemängd
A.3 MySql - Filtrering
Product
Fält Typ Värdemängd
id Int 1 till MAX id
title Varchar(15) En Sträng mellan 2 och 12 tecken
description Text En Sträng mellan 0 och 200 tecken
quantity Int Nummer mellan 0 och 1000
Category
Fält Typ Värdemängd
id Int 1 till MAX id
title Varchar(15) En Sträng mellan 2 och 12 tecken
ProductCategory
Fält Typ Värdemängd
productId Int Id till en existerande produkt
A.4 MongoDb - Filtrering
A.4.1 Med relationer Product
Fält Typ Värdemängd
id Int 1 till MAX id
title Varchar(15) En Sträng mellan 2 och 12 tecken
description Text En Sträng mellan 0 och 200 tecken
quantity Int Nummer mellan 0 och 1000
productCategory Array Array med kategorier som
innehål-ler objektId’n till rader som finns i kategori-tabellen
Category
Fält Typ Värdemängd
title Varchar(15) En Sträng mellan 2 och 12 tecken
A.4.2 Utan relationer Product
Fält Typ Värdemängd
title Varchar(15) En Sträng mellan 2 och 12 tecken
description Text En Sträng mellan 0 och 200 tecken
quantity Int Nummer mellan 0 och 1000
B
Källkod
Listing 3: generateData.php <?php define("MIN_AGE",10) ; define("MAX_AGE",99) ; define("MIN_QUANTITY",0) ; define("MAX_QUANTITY",1000) ; define("VARCHAR_MIN", 2) ; define("VARCHAR_MAX", 12) ; define("TEXT_MIN", 0) ; define("TEXT_MAX", 200) ; define("CATEGORIES_MIN", 1) ; define("CATEGORIES_MAX", 10) ; define("CATEGORY", "Ee") ; define("NROFCATEGORIES", 200) ; define('FILE', 'data.txt') ;define('IMAGE', 'bth-logga.jpg') ;
$chars = "0123456789 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
srand(1234) ;
// Generate random string with an exaclty length f u n c t i o n rand_string($length) { g l o b a l $chars; $ s t r = ""; $ s i z e = s t r l e n($chars) ; f o r($ i = 0 ;$ i < $length; $ i++ ) { $ s t r .= $chars[rand(0 ,$ s i z e − 1) ] ; } return $ s t r; }
// Generate random string between min and max f u n c t i o n rand_string_between($min,$max) {
$length = rand($min,$max) ;
return rand_string($length) ; }
// Generate Member
f u n c t i o n generate_member( ) { $member = array( ) ;
$member["firstName"] = rand_string_between(VARCHAR_MIN,VARCHAR_MAX) ; $member["username"] = rand_string_between(VARCHAR_MIN,VARCHAR_MAX) ; $member["lastName"] = rand_string_between(VARCHAR_MAX,VARCHAR_MAX) ; $member["age"] = rand(MIN_AGE,MAX_AGE) ;
return $member; }
$category = array( ) ;
$category["title"] = rand_string_between(VARCHAR_MIN, VARCHAR_MAX) ; return $category; } f u n c t i o n g e n e r a t e _ c a t e g o r i e s( ) { $ c a t e g o r i e s = array( ) ; f o r($ i = 0 ; $ i < NROFCATEGORIES; $ i++) { array_push($ c a t e g o r i e s ,generate_category( ) ) ; } return $ c a t e g o r i e s; } f u n c t i o n g e ner a te _ c at e g o rie s_ i d s( ) {
$nrOfCats = rand(CATEGORIES_MIN, CATEGORIES_MAX) ;
$ c a t e g o r i e s I d s = array( ) ;
$count = 0 ;
while($count < $nrOfCats ) { $id = rand(1 ,NROFCATEGORIES) ;
i f ( !in_array($id, $ c a t e g o r i e s I d s) ) { array_push($ c a t e g o r i e s I d s ,$id) ; $count++; } } return $ c a t e g o r i e s I d s; } // Generate product f u n c t i o n generate_product( ) { $product = array( ) ;
$product["title"] = rand_string_between(VARCHAR_MIN, VARCHAR_MAX) ;
$product["description"] = rand_string_between(TEXT_MIN,TEXT_MAX) ; $product["quantity"] = rand(MIN_AGE,MAX_AGE) ;
return $product; } ?> Listing 4: insertMysql.php <?php require_once("generateData.php") ;
define('DB_HOST', 'localhost') ; define('DB_NAME', 'thesis') ; define('DB_USER', 'thesis') ; define('DB_PASSWORD', 'wip') ;
die("ERROR: Database Connection failed , Mysql Message: ".$this−>db−> connect_error) ;
}
// Force Utf -8 communication $db−>set_charset('utf8') ;
// Get parameters from commandline $options = getopt("t:n:") ;
i f ( !i s s e t($options["n"] ) | | !i s s e t($options["t"] ) | | !is_numeric($options["n"
] ) ) {
die("ERROR: Optionsparameters is invalid!\n") ;
}
define("TYPE",$options["t"] ) ; define("NROFLOOPS",$options["n"] ) ;
// Generate data and save to file i f(TYPE == "g") {
i f (f i l e _ e x i s t s(FILE) ) {
unlink(FILE) ; }
$handle = fopen(FILE, 'w') or die('Cannot open file: '.FILE) ; f o r($ i=0;$ i < NROFLOOPS; $ i++ ) {
$member = generate_member( ) ;
$query = "INSERT INTO Member (firstName , lastName , username , age) VALUES('".$member["firstName"] ."', '".$member["lastName"] ."', '". $member["username"] ."', '".$member["age"] ."');";
f w r i t e($handle, $query."\n") ; } f c l o s e($handle) ; } i f(TYPE == "gm") { i f (f i l e _ e x i s t s(FILE) ) { unlink(FILE) ; }
$handle = fopen(FILE, 'w') or die('Cannot open file: '.FILE) ;
$query = "INSERT INTO Member (firstName , lastName , username , age) VALUES";
f o r($ i=0;$ i < NROFLOOPS; $ i++ ) {
$member = generate_member( ) ;
$query.="('".$member["firstName"] ."', '".$member["lastName"] ."', '". $member["username"] ."', '".$member["age"] ."'),";
}
$query = substr($query, 0 , −1) ; f w r i t e($handle, $query."\n") ; f c l o s e($handle) ;
}
e l s e i f(TYPE == "i") {
i f ( !f i l e _ e x i s t s(FILE) ) {
die("ERROR: Please run setup first to create data file!") ;
}
$handle = fopen(FILE, "r") ;
i f($handle) {
while( ($ b u f f e r = f g e t s($handle, 4096) ) !== f a l s e) {
$db−>query($ b u f f e r) or die($db−>e r r o r) ; }
i f ( !f e o f($handle) ) {
echo "Error: unexpected fgets() fail\n";
}
f c l o s e($handle) ;
// Clear data file
echo "Insert complete!";
unlink(FILE) ; }
}
e l s e i f(TYPE == "im") {
i f ( !f i l e _ e x i s t s(FILE) ) {
die("ERROR: Please run setup first to create data file!") ;
}
$ b u f f e r=file_get_contents(FILE) ;
$db−>query($ b u f f e r) or die($db−>e r r o r) ; // Clear data file
echo "Insert complete!";
}
// Save images
e l s e i f(TYPE == "img") { i f( !f i l e _ e x i s t s(IMAGE) ) {
die("ERROR: Image not found!") ;
}
$image = chunk_split(base64_encode(file_get_contents(IMAGE) ) ) ; f o r($ i=0;$ i < NROFLOOPS; $ i++ ) {
$query = "INSERT INTO Image (image) VALUES('$image ')"; $db−>query($query) or die($db−>e r r o r) ;
// select a collection
$ c o l l e c t i o n = $db−>Members; $ c o l l e c t i o n I m a g e = $db−>image;
$grid = $db−>getGridFS( ) ; // Get parameters from commandline $options = getopt("t:n:") ;
i f ( !i s s e t($options["n"] ) | | !i s s e t($options["t"] ) | | !is_numeric($options["n"
] ) ) {
die("ERROR: Optionsparameters is invalid!\n") ;
}
define("NROFLOOPS",$options["n"] ) ; define("TYPE",$options["t"] ) ;
// Generate data and save to file i f(TYPE == "g") {
i f (f i l e _ e x i s t s(FILE) ) {
unlink(FILE) ; }
$handle = fopen(FILE, 'w') or die('Cannot open file: '.FILE) ; f o r($ i=0;$ i < NROFLOOPS; $ i++ ) { $member = generate_member( ) ; f w r i t e($handle, s e r i a l i z e($member) ."\n") ; } f c l o s e($handle) ; }
// Read from file and insert data to database e l s e i f(TYPE == "i") {
i f ( !f i l e _ e x i s t s(FILE) ) {
die("ERROR: Please run setup first to create data file!") ;
}
$handle = fopen(FILE, "r") ;
i f($handle) {
while( ($ b u f f e r = f g e t s($handle, 4096) ) !== f a l s e) {
$ c o l l e c t i o n−>i n s e r t(u n s e r i a l i z e($ b u f f e r) ) ; }
i f ( !f e o f($handle) ) {
echo "Error: unexpected fgets() fail\n";
}
f c l o s e($handle) ;
// Clear data file
echo "Insert complete!";
unlink(FILE) ; } } // BatchInsert eq MultiQuery e l s e i f(TYPE == "im") { i f ( !f i l e _ e x i s t s(FILE) ) {
}
$handle = fopen(FILE, "r") ;
$members = array( ) ; i f($handle) { while( ($ b u f f e r = f g e t s($handle, 4096) ) !== f a l s e) { array_push($members, u n s e r i a l i z e($ b u f f e r) ) ; } i f ( !f e o f($handle) ) {
echo "Error: unexpected fgets() fail\n";
}
f c l o s e($handle) ;
// Insert all members
$ c o l l e c t i o n−>b a t c h I n s e r t($members) ; // Clear data file
echo "batchInsert complete!";
unlink(FILE) ; } } // Save image e l s e i f(TYPE == "img") { i f( !f i l e _ e x i s t s(IMAGE) ) {
die("ERROR: Image not found!") ;
}
$arr = array( ) ;
$ r e f = &$arr;
$arr["image"] = chunk_split(base64_encode(file_get_contents(IMAGE) ) ) ; f o r($ i=0;$ i < NROFLOOPS; $ i++ ) {
$ s t a t u s = $ c o l l e c t i o n I m ag e−>i n s e r t($ r e f) ; }
}
// Save image grid fs e l s e i f(TYPE == "fsimg") {
i f( !f i l e _ e x i s t s(IMAGE) ) {
die("ERROR: Image not found!") ;
}
//$image = chunk_split(base64_encode(file_get_contents(IMAGE))); $fileName = "Image";
f o r($ i=0;$ i < NROFLOOPS; $ i++ ) {
// Note metadata field & filename field $ s t o r e d f i l e = $grid−>s t o r e F i l e(IMAGE,
array("metadata" => array("filename" => $fileName) ,
"filename" => $fileName) ) ; }
} ?>
<?php
require_once("generateData.php") ;
define('DB_HOST', 'localhost') ; define('DB_NAME', 'thesis') ; define('DB_USER', 'thesis') ; define('DB_PASSWORD', 'wip') ;
$db = new mysqli(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME) ; i f ($db−>connect_errno) {
die("ERROR: Database Connection failed , Mysql Message: ".$this−>db−> connect_error) ;
}
// Force Utf -8 communication $db−>set_charset('utf8') ;
// Get parameters from commandline $options = getopt("t:n:") ;
i f ( !i s s e t($options["n"] ) | | !i s s e t($options["t"] ) | | !is_numeric($options["n"
] ) ) {
die("ERROR: Optionsparameters is invalid!\n") ;
}
define("TYPE",$options["t"] ) ; define("NROFLOOPS",$options["n"] ) ;
i f(TYPE == "q") {
$query = "SELECT Product . * , Category . * FROM ProductCategory
INNER JOIN Product ON ProductCategory.productId = Product.id
LEFT OUTER JOIN Category ON ProductCategory.categoryId = Category.id WHERE Category.title = '" .CATEGORY."'";
$db−>query($query) or die($db−>e r r o r) ; }
// Generate data
e l s e i f(TYPE == "g") { //Insert all categories
$ c a t e g o r i e s = g e n e r a t e _ c a t e g o r i e s( ) ;
foreach ($ c a t e g o r i e s as $category) {
$query = "INSERT INTO Category (title) VALUES('".$category["title"] ."');"; $db−>query($query) or die($db−>e r r o r) ; }
// Generate products
f o r($ i=0;$ i < NROFLOOPS; $ i++ ) {
$query = "INSERT INTO Product (title , description , quantity)
VALUES('".$product["title"] ."', '".$product["description"] ."', '". $product["quantity"] ."');";
$db−>query($query) or die($db−>e r r o r) ;
$productId = $db−>i n s e r t _ i d;
$ c a te g o r y I ds = g e ne r ate_ c at eg or ie s_id s( ) ;
foreach ($ c a t e go r y I ds as $categoryId) {
$query = "INSERT INTO ProductCategory (productId , categoryId) VALUES('".$productId."', '".$categoryId."');";
$db−>query($query) or die($db−>e r r o r) ; }
} }
//Clear data
e l s e i f(TYPE == "c") {
$db−>query("TRUNCATE TABLE Product") or die($db−>e r r o r) ;
$db−>query("TRUNCATE TABLE ProductCategory") or die($db−>e r r o r) ; $db−>query("TRUNCATE TABLE Category") or die($db−>e r r o r) ;
} ?> Listing 7: queryMongoDb.php <?php require_once("generateData.php") ; // connect $m = new Mongo( ) ; // select a database $db = $m−>t h e s i s; // select a collection $ c o l l e c t i o n C a t e g o r y = $db−>Category; $ c o l l e c t i o n P r o d u c t = $db−>Product; // Get parameters from commandline $options = getopt("t:n:") ;
i f ( !i s s e t($options["n"] ) | | !i s s e t($options["t"] ) | | !is_numeric($options["n"
] ) ) {
die("ERROR: Optionsparameters is invalid!\n") ;
}
// Generate data with relations and insert into database i f(TYPE == "g") { $ i n s e r t e d C a t e g o r i e s = array( ) ; $ c a t e g o r i e s = g e n e r a t e _ c a t e g o r i e s( ) ; foreach($ c a t e g o r i e s as $cat) { $ c o l l e c t i o n C a t e g o r y−>i n s e r t($cat) ; array_push($ i n s e r t e d C a t e g o r i e s , $cat) ; } f o r($ i=0; $ i < NROFLOOPS; $ i++ ) { $product = generate_product( ) ; $productCategoryIds = g e ne ra te _ ca te go ri e s_i ds( ) ; $productCategoryArray = array( ) ;
foreach($productCategoryIds as $catId) {
$currentCat = $ i n s e r t e d C a t e g o r i e s[$catId−1];
array_push($productCategoryArray, $currentCat['_id'] ) ;
}
$product['productCategory'] = $productCategoryArray; $ c o l l e c t i o n P r o d u c t−>i n s e r t($product) ;
} }
// Generate data for noqsl standard way and insert inte database i f(TYPE == "g2") {
$ i n s e r t e d C a t e g o r i e s = array( ) ;
$ c a t e g o r i e s = g e n e r a t e _ c a t e g o r i e s( ) ;
f o r($ i=0; $ i < NROFLOOPS; $ i++ ) {
$product = generate_product( ) ;
$productCategoryIds = ge ne r at e _cat e go rie s_ ids( ) ; $productCategoryArray = array( ) ;
foreach($productCategoryIds as $catId) {
$currentCat = $ c a t e g o r i e s[$catId−1];
array_push($productCategoryArray, $currentCat['title'] ) ;
}
$product['productCategory'] = $productCategoryArray; $ c o l l e c t i o n P r o d u c t−>i n s e r t($product) ;
} }
// clear all data in database e l s e i f(TYPE == "c") {
$ c o l l e c t i o n P r o d u c t−>remove( ) ; $ c o l l e c t i o n C a t e g o r y−>remove( ) ; }
// query database relational e l s e i f(TYPE == "q") {
$categoryObject = $ c o l l e c t i o n C a t e g o r y−>f i n d(array('title' =>CATEGORY) ) ; foreach ($categoryObject as $doc) {
$cursor = $ c o l l e c t i o n P r o d u c t−>f i n d(array('productCategory' => $doc['
}
$result Ar r ay = iterator_to_array($cursor) ; }
// query database not relational e l s e i f(TYPE == "q2") {
$cursor = $ c o l l e c t i o n P r o d u c t−>f i n d(array('productCategory' =>CATEGORY) ) ;
$ resul t Ar r ay = iterator_to_array($cursor) ; }
C
Diagram
C.1 Insättning av data Ubuntu 64
0 10 20 30 40 50 60 70 1000 10000 100000 10000000 Tid(s) Antal MySql MongoDb
C.2 Insättning av data Ubuntu 32
C.3 Filtrering av data Ubuntu 64 0 10 20 30 40 50 60 70 80 90 1000 10000 100000 10000000 40000000 Tid(s) Antal MySql MongoDb utan relationer MongoDb med relationer
C.4 Filtrering av data Ubuntu 32