Kandidatavhandling i Programvaruteknik
06 2012
Jämförelse av Mysql och MongoDb
Alfred Wester
Olof Fredriksson
Kontaktinformation:
Författare:
Alfred Wester
E-mail: [email protected]
Olof Fredriksson
E-mail: [email protected]
Handledare:
Nina D. Fogelström
School of Computing
Sektionen för datavetenskap och kommunikation
Blekinge Tekniska Högskola
371 79 Karlskrona
Sweden
Internet : www.bth.se/com
Phone : +46 455 38 50 00
Fax
: +46 455 38 50 57
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.
Tests has been done both on inserting and processing when handling up to 4 millions entities, MongoDB
performs better in almost every test. Results shows that the processing time is shorter using MongoDb
in the cases that this thesis is covering, and that it’s possible to implement a much fast application
when using MongoDb instead of Mysql as database.
Innehåll
1
2
3
4
5
6
7
8
Introduktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.1 Målgrupp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Bakgrund . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1 Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 MySql . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3 MongoDb . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.3.1 Gridfs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.4 Multiinsättning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.5 Json . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6 PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Forskningsfrågor och metodik . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.1 Frågeställningar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2 Utformining av litteraturstudie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Resultat från litteraturstudie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.1 Beskrivning av litteratur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2 Resultat och diskussion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
4.2.1 RQ1. Vilka jämförelser av Sql och NoSql-databaser finns redan och hur utformades de?
4.2.2 RQ2. Vilken databas presterar snabbast när det gäller att sätta in och filtrera data? . .
4.2.3 RQ3. Blir det några skillnader på resultatet vid annan uppsättning av miljö? . . . . . . . .
Utformining av experiment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.1 Mål . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Faktorer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.1 PHP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.2 Operativsystem & Hårdvara . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.3 Olika datamodeller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.4 Datamängder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.5 Vad för typ av data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.6 Sätta in all data samtidigt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3 Testmiljö . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.3.1 Systeminformation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.4 Datamodell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Utförande . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.1 Testfall . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.2 Insättning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
6.3 Filtrering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Resultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.1 Insättning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.1.1 Ubuntu 64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.1.2 Ubuntu 32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2 Filtrering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2.1 Ubuntu 64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.2.2 Ubuntu 32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Analys och diskussion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.1 Tester som inte kunde genomföras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 Analys av resultatet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3 Olika sätt att hantera resultatet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.4 Slutsatser . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5
5
5
5
5
6
7
7
7
7
8
8
8
8
9
9
10
11
11
12
12
12
12
12
13
13
13
13
13
14
14
14
14
15
16
17
17
17
18
18
18
19
19
19
20
20
20
9
A
B
C
8.4.1 MongDb är snabbare . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.4.2 MongoDb på ett 32-bitars system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.5 Validering av resultat . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.6 Kopplingar till tidigare arbeten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.7 Framtida arbete . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Sammanfattning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Datamodeller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.1 MySql - Insättning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.2 MongoDb - Insättning . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.3 MySql - Filtrering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4 MongoDb - Filtrering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4.1 Med relationer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
A.4.2 Utan relationer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Källkod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
C.1 Insättning av data Ubuntu 64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
C.2 Insättning av data Ubuntu 32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
C.3 Filtrering av data Ubuntu 64 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
C.4 Filtrering av data Ubuntu 32 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
20
21
21
21
21
22
26
26
26
27
28
28
28
29
39
39
39
40
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äremot 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 rekommenderar ändå att man har några tidigare erfarenheter antingen genom att ha jobbat med databaser eller kan
grundprinciperna om hur de fungerar.
2
2.1
Bakgrund
Data
Data, 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 liknande operationer.
Om man nu ska använda tabellen till medlemmar och sedan skapa en enkel form av en blogg, med inlägg och
5
kommentarer kan detta sparas i två separata tabeller. Givetvis är det möjligt att spara användarinformationen 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 ` a s P INNER JOIN Member a s 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.
MongoDb’s motsvarighet till tabeller heter Collections men varje objekt som sätts in kan vara helt olika
varandra, det finns inget bestämt vad som ska finnas där. En annan skillnad i jämförelse till MySql är att
det även är möjligt att spara ned array’s direkt i objektet. Det kan sparas väldigt mycket tid att ha denna
data direkt i objektet än om det funnits i en annan tabell. Däremot kan det behövas mer logik i programmet
som hanterar datan, då det inte finns några garantier att datan ser ut på ett visst sätt.
6
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 fd230266803fa9d100003e7 " ) ,
" title " : " Awesome post " ,
" content " : " Lorem ipsum dolor sit amet , consectetur adipiscing 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 bulkinsert[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 databasen 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 dynamiskt med hjälp av Javascript.
{
" firstName " : " John " ,
" lastName " : " Doe " ,
" phoneNo " : " +4600012 " ,
" active " : true
}
Listing 2: Ett exempel på hur ett Json-objekt kan se ut
2.6
PHP
PHP[13], som är en rekursiv akronym för PHP Hypertext Preprocessor, är ett populärt programmeringspråk.
Användningsområdet är främst inom webbutveckling och används för att till exempel göra beräkningar
eller hämta information från en databas. Koden exekveras på serversidan och all utskrift skickas ned till
webbläsaren tillsammans med html-koden. PHP används dock inte bara till webbsidor utan det går även att
använda direkt via konsolen[14].
7
3
3.1
Forskningsfrågor och metodik
Frågeställningar
Arbetet 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
Nedan beskrivs litteraturen från litteraturstudien(sektion 4.1) och vilka av de funna artiklarna som relaterar
till vilken forskningsfråga(tabell 2) I sektion 4.2 presenteras även resultaten som sedan diskuteras utifrån
studien.
8
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 databastyperna 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 [3]
using a Python interface
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
Det var svårt att hitta artiklar som jämför MySql och NoSql men det ser vi som positivt eftersom detta
arbete blir mer betydelsefullt och kan ge mer värde. Det visade sig vara enklare att hitta artiklar om NoSql
än MySql, som inte är för gamla, men vi har ändå lyckats få med båda typerna i vår litteraturstudie. Den
första artikeln(P1) som testar MongoDb och CouchDB gjorde också att MongoDb valdes som den databas
vi ska testa emot MySql, eftersom den var snabbare på de tester som gjorts[3]. Tabell 2 visar vilka artiklar
från litteraturstudien som är relevanta för respektive forskningsfråga.
9
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 artiklar 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 implementera 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 utvärdering kan vara mycket relevant för vårt arbete. Alla utvä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 artikel 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 skalbarhet är viktigt för databasen. Skalbarhet kommer inte att testas i vårt arbete.
I den genomförda litteraturstudien hittades någon enstaka artikel vars syfte är att jämföra SQL - NoSql
som också innehåller experiment för detta. En artikel utför experiment som går ut på att ersätta MySql
10
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ördefinierad 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 experiment.
Henricsson[3] utför tester mellan de två databaserna CouchDb och MongoDb. För att ge MySql en värdig 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 relationer. 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).
Söderberg och Eriksson[15] har även en del information om prestanda. Minne och lagring hanteras inte
likadant mellan olika databaser och därför är det viktigt att ha rätt hårdvara. De tar upp fördelar med att
använda SSD(Solid-state drive), som antagligen ger snabbare resultat för både Sql och NoSql. Söderberg och
Eriksson tar också upp problem kring relationsdatabaser som lagrar stora mängder data där risken för långsamhet är stor. Ett sätt att förbättra prestandan är då att uppgradera hårdvaran. Däremot är det betydligt
11
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. Testerna 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 administrationsgrä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
Val av operativsystem och hårdvara kan ha stor påverkan på testresultaten. Experimenten kommer därför att
köras på två olika datorer med olika versioner av os. De operativsystem som valts är Ubuntu GNU/Linux
10.04 LTS 32 respektive 64 bitarsversion eftersom Ubuntu var det os som presterade bäst i jämförelse
med fedora[22]. Specifikationer för respektive dator som kommer att användas finns under sektion 5.3.1
Systeminformation.
12
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 databas. 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ämfö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".
Den tid som kommer att användas under experimenten i detta arbetet är Real.
13
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ångafö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 Systeminformation, 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
Tabellerna nedan visar alla testfall som ska utföras. Varje testfall kommer att köras fem gånger och sedan
ska medelvärdet av resultaten räknas ut. Detta för att tiderna kan variera mellan varje körning.
14
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
Tabell 3: Samtliga tester som kommer genomföras för insättning
15
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
Tabell 4: Samtliga tester som kommer genomföras för filtrering
16
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
1
Member
1000
nej
0,146
0,122
2
Image
1000
nej
3,859
1,353
3
Member
10 000
nej
0,712
0,310
4
Image
10 000
nej
43,515
50,170
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
Tabell 5: Resultat för testerna med insättning på Ubuntu 64
17
GridFs
3,385
53,603
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
9
Member
1000
nej
0,079
0,048
10
Image
1000
nej
4,693
0,788
11
Member
10 000
nej
0,479
0,299
12
Image
10 000
nej
47,207
18,327
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
GridFs
0
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
Tabell 7: Resultat för testerna med filtrering på Ubuntu 64
18
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 fallerade 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 for larger datasets
Vi var medvetna om gränserna på ett 32-bitars system men då borde inte heller de tidigare testerna med
bilder fungerat. Felen började istället uppstå efter att datorn startats om och det är fortfarande oklart varför
problemen uppkom just då och inte tidigare. Det gjordes ett par försök att reparera databasen, vilket även
lyckades en gång men problemet återuppstod ganska snart, så dessa tester fick tyvärr avbrytas.
19
8.2
Analys av resultatet
Figur 2 visar tidsskillnaderna mellan MySql och
MongdoDb vid insättning. Diagrammet visar tydligt att MySql tar längre tid på sig än sin konkurrent, speciellt vid insättningen av det högsta antalet 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 ökning.
70
MySql
MongoDb
60
Tid(s)
50
40
30
20
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 sekund för båda databaserna vilket inte anses speciellt
mycket.
10
0
1000
10000
100000
10000000
Antal
Figur 2: Ubuntu 64, Insättning av data
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 testerna på grund av den gräns som finns för objekten. Resultaten för 32-bitarsdatorn visar liknande 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.
Även om det inte är vanligt att sätta in större mängder 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 experimentet var relativt enkel, men ändå kan man se att
MongoDb är betydligt snabbare än MySql.
Vid filtrering av 4 miljoner produkter skiljer det ungefär 70 sekunder, vilket är en enorm skillnad. Skillnaderna 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 vilket inte anses speciellt mycket i jämförelse till Mysql.
8.3
90
MySql
MongoDb utan relationer
MongoDb med relationer
80
70
Tid(s)
60
50
40
30
20
10
0
1000
10000
100000
10000000
40000000
Antal
Figur 3: Ubuntu 64 : Filtrering av data
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
8.4.1
Slutsatser
MongDb är snabbare
Med få undantag vann MongoDb på samtliga tester som genomfördes för de båda systemen. Det går alltså att
vinna mycket tid vid hantering av större mängder data, samtidigt som en viss struktur av relationer mellan
collections kan finnas likt MySqls tabellrelationer. Det största testet som genomfördes här var dessutom
20
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 medelvä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 databaserna, 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
Databasstrukturen som användes under jämförelse av filtrering är bara ett av många olika fall där man är
i behov av någon form av relationer. Att utföra tester med ytterligare och mer avancerade relationer hade
varit intressant då man åter kan se styrkan med MongoDb’s snabbhet där MySql inte riktigt hänger med.
Ett exempel på en lite mer avancerad relation är att ha en separat tabell för pris, som läggs till i strukturen
för produkter och kategorier som användes i detta arbete. Då skulle denna tabell hantera daglig historik för
produktens prisutveckling. Om det t.ex. finns totalt 5000 produkter och en historik med prisutveckling för
21
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].
Även om det kanske inte finns någon direkt anledning använda Mysql i de fallen som exerimenten innehöll så finns det dock fortfarande fördelar att hålla sig kvar vid MySql. Även om det finns ett visst stöd för
relationer i MongoDb så finns det inte alls lika mycket funktionalitet som MySql innehåller, vilket just är
22
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.
Mysql har även funnits ute längre, så alla dessa problem som nya program kan innehålla är lösta, samtidigt som kompetensen kring detta är större än för MongoDb. Ett problem är ju till exempel begränsningen
på 16mb vid insättning av data vilket helt enkelt inte är godtagbart, men troligtvis är det något som kommer
att lösas inom kort.
23
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.
http://devzone.zend.com/1730/getting-started-with-mongodb-and-php/, 2010.
24
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.
http://www.mongodb.org/display/DOCS/Drivers.
25
A
Datamodeller
A.1
MySql - Insättning
Member
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
Fält
Typ
Värdemängd
id
Int
1 till MAX id
image
MediumBlob
Bild i binär form
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
Fält
Typ
Värdemängd
image
Sträng
Bild i binär form
Image
A.2
MongoDb - Insättning
Member
Image
26
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
Fält
Typ
Värdemängd
id
Int
1 till MAX id
title
Varchar(15)
En Sträng mellan 2 och 12 tecken
Fält
Typ
Värdemängd
productId
Int
Id till en existerande produkt
categoryId
Int
Id till en existerande kategori
Category
ProductCategory
27
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åller objektId’n till rader som finns i
kategori-tabellen
Fält
Typ
Värdemängd
title
Varchar(15)
En Sträng mellan 2 och 12 tecken
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
productCategory
Array
Array med kategorier
Category
A.4.2
Utan relationer
Product
28
B
Källkod
Listing 3: generateData.php
<?php
define ( " MIN_AGE " , 1 0 ) ;
define ( " MAX_AGE " , 9 9 ) ;
define ( " MIN_QUANTITY " , 0 ) ;
define ( " MAX_QUANTITY " , 1 0 0 0 ) ;
define ( " VARCHAR_MIN " , 2 ) ;
define ( " VARCHAR_MAX " , 1 2 ) ;
define ( " TEXT_MIN " , 0 ) ;
define ( " TEXT_MAX " , 2 0 0 ) ;
define ( " CATEGORIES_MIN " , 1 ) ;
define ( " CATEGORIES_MAX " , 1 0 ) ;
define ( " CATEGORY " , "Ee" ) ;
define ( " NROFCATEGORIES " , 2 0 0 ) ;
define ( 'FILE ' , 'data.txt ' ) ;
define ( 'IMAGE ' , 'bth - logga .jpg ' ) ;
$ c h a r s = " 0123456789 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
srand ( 1 2 3 4 ) ;
// Generate random string with an exaclty length
function rand_string ( $length ) {
global $chars ;
$ s t r = "" ;
$ s i z e = strlen ( $chars ) ;
f o r ( $ i = 0 ; $ i < $ l e n g t h ; $ i++ ) {
$ s t r .= $ c h a r s [ rand ( 0 , $ s i z e − 1 ) ] ;
}
return $str ;
}
// Generate random string between min and max
f u n c t i o n rand_string_between ( $min , $max ) {
$ l e n g t h = rand ( $min , $max ) ;
return rand_string ( $length ) ;
}
// Generate Member
f u n c t i o n generate_member ( ) {
$member = array ( ) ;
$member [ " firstName " ]
=
$member [ " username " ]
=
$member [ " lastName " ]
=
$member [ "age" ]
=
r e t u r n $member ;
}
rand_string_between (VARCHAR_MIN,VARCHAR_MAX) ;
rand_string_between (VARCHAR_MIN,VARCHAR_MAX) ;
rand_string_between (VARCHAR_MAX,VARCHAR_MAX) ;
rand (MIN_AGE,MAX_AGE) ;
function generate_category () {
29
}
$ c a t e g o r y = array ( ) ;
$ c a t e g o r y [ " title " ]
VARCHAR_MAX) ;
return $category ;
=
rand_string_between (VARCHAR_MIN,
function generate_categories () {
$ 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 , g e n e r a t e _ c a t e g o r y ( ) ) ;
}
return $categories ;
}
function generate_categories_ids () {
$nrOfCats = rand (CATEGORIES_MIN, CATEGORIES_MAX) ;
$ c a t e g o r i e s I d s = array ( ) ;
$count = 0 ;
w h i l e ( $count < $nrOfCats ) {
$ i d = 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 , $ i d ) ;
$count++;
}
}
return $categoriesIds ;
}
// Generate product
function generate_product ( ) {
$ p r o d u c t = array ( ) ;
$ p r o d u c t [ " title " ]
VARCHAR_MAX) ;
$ p r o d u c t [ " description " ]
$ p r o d u c t [ " quantity " ]
return $product ;
}
=
rand_string_between (VARCHAR_MIN,
=
=
rand_string_between (TEXT_MIN,TEXT_MAX) ;
rand (MIN_AGE,MAX_AGE) ;
?>
Listing 4: insertMysql.php
<?php
r e q u i r e _ o n c e ( " generateData .php" ) ;
define ( 'DB_HOST ' , 'localhost ' ) ;
define ( 'DB_NAME ' , 'thesis ' ) ;
define ( 'DB_USER ' , 'thesis ' ) ;
define ( 'DB_PASSWORD ' , 'wip ' ) ;
$db = new m y s q l i (DB_HOST,DB_USER,DB_PASSWORD,DB_NAME) ;
i f ( $db−>c o n n e c t _ e r r n o ) {
30
}
die ( " ERROR : Database Connection failed , Mysql Message : " . $ t h i s −>db−>
connect_error ) ;
// Force Utf -8 communication
$db−>s e t _ c h a r s e t ( 'utf8 ' ) ;
// Get parameters from commandline
$ o p t i o n s = g e t o p t ( "t:n:" ) ;
i f ( ! i s s e t ( $ o p t i o n s [ "n" ] ) | | ! i s s e t ( $ o p t i o n s [ "t" ] ) | | ! is_numeric ( $ o p t i o n s [ "n"
]) ) {
die ( " ERROR : Optionsparameters is invalid !\n" ) ;
}
define ( "TYPE" , $ o p t i o n s [ "t" ] ) ;
define ( " NROFLOOPS " , $ o p t i o n s [ "n" ] ) ;
// Generate data and save to file
i f (TYPE == "g" ) {
i f ( f i l e _ e x i s t s ( FILE ) ) {
u n l i n k ( FILE ) ;
}
$ h a n d l e = fopen ( FILE , 'w' ) o r 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" ] . " ');" ;
fwrite ( $handle , $query . "\n" ) ;
}
fclose ( $handle ) ;
}
i f (TYPE == "gm" ) {
i f ( f i l e _ e x i s t s ( FILE ) ) {
u n l i n k ( FILE ) ;
}
$ h a n d l e = fopen ( FILE , 'w' ) o r 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) ;
fwrite ( $handle , $query . "\n" ) ;
fclose ( $handle ) ;
}
// Read from file and insert data to database
31
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!" ) ;
}
$ h a n d l e = fopen ( FILE , "r" ) ;
i f ( $handle ) {
w h i l e ( ( $ b u f f e r = f g e t s ( $handle , 4 0 9 6 ) ) !== f a l s e ) {
$db−>query ( $ b u f f e r ) o r die ( $db−>e r r o r ) ;
}
i f ( ! feof ( $handle ) ) {
echo " Error : unexpected fgets () fail\n" ;
}
fclose ( $handle ) ;
// Clear data file
echo " Insert complete !" ;
u n l i n k ( 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 ) o r 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 ) o r die ( $db−>e r r o r ) ;
}
}
?>
Listing 5: insertMongoDb.php
<?php
r e q u i r e _ o n c e ( " generateData .php" ) ;
// connect
$m = new Mongo ( ) ;
// select a database
$db = $m−>t h e s i s ;
32
// select a collection
$collection
= $db−>Members ;
$collectionImage
= $db−>image ;
$grid
= $db−>getGridFS ( ) ;
// Get parameters from commandline
$ o p t i o n s = g e t o p t ( "t:n:" ) ;
i f ( ! i s s e t ( $ o p t i o n s [ "n" ] ) | | ! i s s e t ( $ o p t i o n s [ "t" ] ) | | ! is_numeric ( $ o p t i o n s [ "n"
]) ) {
die ( " ERROR : Optionsparameters is invalid !\n" ) ;
}
define ( " NROFLOOPS " , $ o p t i o n s [ "n" ] ) ;
define ( "TYPE" , $ o p t i o n s [ "t" ] ) ;
// Generate data and save to file
i f (TYPE == "g" ) {
i f ( f i l e _ e x i s t s ( FILE ) ) {
u n l i n k ( FILE ) ;
}
$ h a n d l e = fopen ( FILE , 'w' ) o r die ( 'Cannot open file: ' . FILE ) ;
f o r ( $ i =0; $ i < NROFLOOPS; $ i++ ) {
$member = generate_member ( ) ;
fwrite ( $handle , s e r i a l i z e ( $member ) . "\n" ) ;
}
fclose ( $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!" ) ;
}
$ h a n d l e = fopen ( FILE , "r" ) ;
i f ( $handle ) {
w h i l e ( ( $ b u f f e r = f g e t s ( $handle , 4 0 9 6 ) ) !== 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 ( ! feof ( $handle ) ) {
echo " Error : unexpected fgets () fail\n" ;
}
fclose ( $handle ) ;
// Clear data file
echo " Insert complete !" ;
u n l i n k ( 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 ) ) {
die ( " ERROR : Please run setup first to create data file!" ) ;
33
}
}
$ h a n d l e = fopen ( FILE , "r" ) ;
$members = array ( ) ;
i f ( $handle ) {
w h i l e ( ( $ b u f f e r = f g e t s ( $handle , 4 0 9 6 ) ) !== 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 ( ! feof ( $handle ) ) {
echo " Error : unexpected fgets () fail\n" ;
}
fclose ( $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 !" ;
u n l i n k ( 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 !" ) ;
}
$ a r r = array ( ) ;
$ r e f = &$ a r r ;
$ a r r [ " 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 a g 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 )));
$ f i l e N a m e = " Image " ;
f o r ( $ i =0; $ i < NROFLOOPS; $ i++ ) {
// Note metadata field & filename field
$ s t o r e d f i l e = $ g r i d −>s t o r e F i l e (IMAGE,
array ( " metadata " => array ( " filename " => $ f i l e N a m e ) ,
" filename " => $ f i l e N a m e ) ) ;
}
?>
}
Listing 6: queryMysql.php
34
<?php
r e q u i r e _ o n c e ( " generateData .php" ) ;
define ( 'DB_HOST ' , 'localhost ' ) ;
define ( 'DB_NAME ' , 'thesis ' ) ;
define ( 'DB_USER ' , 'thesis ' ) ;
define ( 'DB_PASSWORD ' , 'wip ' ) ;
$db = new m y s q l i (DB_HOST,DB_USER,DB_PASSWORD,DB_NAME) ;
i f ( $db−>c o n n e c t _ e r r n o ) {
die ( " ERROR : Database Connection failed , Mysql Message : " . $ t h i s −>db−>
connect_error ) ;
}
// Force Utf -8 communication
$db−>s e t _ c h a r s e t ( 'utf8 ' ) ;
// Get parameters from commandline
$ o p t i o n s = g e t o p t ( "t:n:" ) ;
i f ( ! i s s e t ( $ o p t i o n s [ "n" ] ) | | ! i s s e t ( $ o p t i o n s [ "t" ] ) | | ! is_numeric ( $ o p t i o n s [ "n"
]) ) {
die ( " ERROR : Optionsparameters is invalid !\n" ) ;
}
define ( "TYPE" , $ o p t i o n s [ "t" ] ) ;
define ( " NROFLOOPS " , $ o p t i o n s [ "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 ) o r die ( $db−>e r r o r ) ;
}
// Generate data
e l s e i f (TYPE == "g" ) {
// Insert all categories
$categories = generate_categories () ;
foreach ( $ c a t e g o r i e s a s $ c a t e g o r y ) {
$query = " INSERT INTO Category ( title )
VALUES ('" . $ c a t e g o r y [ " title " ] . " ');" ;
$db−>query ( $query ) o r die ( $db−>e r r o r ) ;
}
// Generate products
f o r ( $ i =0; $ i < NROFLOOPS; $ i++ ) {
$product = generate_product ( ) ;
35
$query = " INSERT INTO Product (title , description , quantity )
VALUES ('" . $ p r o d u c t [ " title " ] . "', '" . $ p r o d u c t [ " description " ] . "', '" .
$ p r o d u c t [ " quantity " ] . " ');" ;
$db−>query ( $query ) o r die ( $db−>e r r o r ) ;
$ p r o d u c t I d = $db−>i n s e r t _ i d ;
$categoryIds = generate_categories_ids () ;
foreach ( $ c a t e g o r y I d s a s $ c a t e g o r y I d ) {
$query = " INSERT INTO ProductCategory (productId , categoryId )
VALUES ('" . $ p r o d u c t I d . "', '" . $ c a t e g o r y I d . " ');" ;
$db−>query ( $query ) o r die ( $db−>e r r o r ) ;
}
}
}
// Clear data
e l s e i f (TYPE == "c" ) {
$db−>query ( " TRUNCATE TABLE Product " ) o r die ( $db−>e r r o r ) ;
$db−>query ( " TRUNCATE TABLE ProductCategory " ) o r die ( $db−>e r r o r ) ;
$db−>query ( " TRUNCATE TABLE Category " ) o r die ( $db−>e r r o r ) ;
}
?>
Listing 7: queryMongoDb.php
<?php
r e q u i r e _ o n c e ( " 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
$ o p t i o n s = g e t o p t ( "t:n:" ) ;
i f ( ! i s s e t ( $ o p t i o n s [ "n" ] ) | | ! i s s e t ( $ o p t i o n s [ "t" ] ) | | ! is_numeric ( $ o p t i o n s [ "n"
]) ) {
die ( " ERROR : Optionsparameters is invalid !\n" ) ;
}
define ( " NROFLOOPS " , $ o p t i o n s [ "n" ] ) ;
define ( "TYPE" , $ o p t i o n s [ "t" ] ) ;
36
// 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 ( ) ;
$categories = generate_categories () ;
foreach ( $ c a t e g o r i e s a s $ c a t ) {
$ c o l l e c t i o n C a t e g o r y −>i n s e r t ( $ c a t ) ;
array_push ( $ i n s e r t e d C a t e g o r i e s , $ c a t ) ;
}
f o r ( $ i =0; $ i < NROFLOOPS; $ i++ ) {
$product = generate_product ( ) ;
$productCategoryIds = generate_categories_ids () ;
$productCategoryArray = array ( ) ;
foreach ( $ p r o d u c t C a t e g o r y I d s a s $ c a t I d ) {
$currentCat = $ i n s e r t e d C a t e g o r i e s [ $catId −1];
array_push ( $productCategoryArray , $ c u r r e n t C a t [ '_id ' ] ) ;
}
$ p r o d u c t [ '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 ( $ p r o d u c t ) ;
}
}
// 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 ( ) ;
$categories = generate_categories () ;
f o r ( $ i =0; $ i < NROFLOOPS; $ i++ ) {
$product = generate_product ( ) ;
$productCategoryIds = generate_categories_ids () ;
$productCategoryArray = array ( ) ;
foreach ( $ p r o d u c t C a t e g o r y I d s a s $ c a t I d ) {
$currentCat = $ c a t e g o r i e s [ $catId −1];
array_push ( $productCategoryArray , $ c u r r e n t C a t [ 'title ' ] ) ;
}
$ p r o d u c t [ '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 ( $ p r o d u c t ) ;
}
}
// 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" ) {
$ c a t e g o r y O b j e c t = $ 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 ( $ c a t e g o r y O b j e c t a s $doc ) {
$ c u r s o r = $ c o l l e c t i o n P r o d u c t −>f i n d ( array ( 'productCategory ' => $doc [ '
_id ' ] ) ) ;
37
}
$resultArray = iterator_to_array ( $cursor ) ;
}
// query database not relational
e l s e i f (TYPE == "q2" ) {
$ c u r s o r = $ c o l l e c t i o n P r o d u c t −>f i n d ( array ( 'productCategory ' => CATEGORY) ) ;
$resultArray = iterator_to_array ( $cursor ) ;
}
?>
38
C
C.1
Diagram
Insättning av data Ubuntu 64
70
MySql
MongoDb
60
Tid(s)
50
40
30
20
10
0
1000
10000
100000
10000000
Antal
C.2
Insättning av data Ubuntu 32
45
MySql
MongoDb
40
35
Tid(s)
30
25
20
15
10
5
0
1000
10000
100000
Antal
39
10000000
C.3
Filtrering av data Ubuntu 64
90
MySql
MongoDb utan relationer
MongoDb med relationer
80
70
Tid(s)
60
50
40
30
20
10
0
1000
10000
100000
10000000
40000000
Antal
C.4
Filtrering av data Ubuntu 32
100
MySql
MongoDb utan relationer
MongoDb med relationer
90
80
70
Tid(s)
60
50
40
30
20
10
0
1000
10000
100000
10000000
Antal
40
40000000