Usporedba brzine izvođenja upita između baza podataka MySQL I MongoDB

Jedan od najbitnijih parametara za međusobnu usporedbu različitih vrsta baza podataka je brzina izvođenja upita. Zato smo za današnji tekst napravili jednostavan primjer mjerenja brzine za dva najpopularnija predstavnika u svojim kategorijama - MySQL (relacijske baze podataka) te MongoDB (noSQL baze podataka).

Ideja za organizaciju mjerenja brzine je u biti vrlo jednostavna. Istu vrstu i količinu podataka treba spremiti u obje baze podataka, te nakon toga napraviti mjerenje brzine rada na što sličnijim upitima. Naravno, tako jednostavno mjerenje ne može dati konačni odgovor o ukupnim performansama obaju sustava, jer bi za tako nešto trebalo pripremiti bitno složenije modele podataka, koristiti vrlo složene vrste upita i funkcija u njima i slično. Primjer ipak može poslužiti za dobivanje početnog dojma o tome je li jedna vrsta sustava u pogledu brzine bitno drugačija od druge vrste.

 

slika01.png

Slika 1. MySQL baza je pripremljena pomoću besplatnog alata dostupnog na adresi http://filldb.info/

 

Za pripremu MySQL baze za testiranje upotrijebljen je javno dostupan alat na web-adresi http://filldb.info/. Osim same strukture baze, pomoću navedenog alata moguće je prema zadanim pravilima pripremiti i željeni broj slogova u tablicama. Na samom kraju postupka bazu podataka moguće je izvesti u obliku standardnih SQL naredbi za korištenje na bilo kojem MySQL sustavu.

Test baza u ovom primjeru sastoji se od dviju tablica s podacima o autorima i njihovim objavama, međusobno povezanih odgovarajućom relacijom. Prva tablica sadrži 10.000 slogova, a druga 20.000 slogova.

Cjelokupna struktura baze podataka, zajedno s prvim slogom za svaku od tablica (da bi se stekao dojam o izgledu podataka), navedena je u nastavku.

 

CREATE TABLE IF NOT EXISTS `authors` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `first_name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `last_name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  `email` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  `birthdate` date NOT NULL,
  `added` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `authors` (`id`, `first_name`, `last_name`, `email`, `birthdate`, `added`) VALUES
       (1, 'Taylor', 'Kreiger', 'judah.jaskolski@example.com', '1993-07-27', '1988-07-17
...

 

CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author_id` int(11) NOT NULL,
  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
  `description` varchar(500) COLLATE utf8_unicode_ci NOT NULL,
  `content` text COLLATE utf8_unicode_ci NOT NULL,
  `date` date NOT NULL,
  PRIMARY KEY (`id`),
  KEY `author` (`author_id`),
  CONSTRAINT `posts_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `authors` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20001 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

 

INSERT INTO `posts` (`id`, `author_id`, `title`, `description`, `content`, `date`) VALUES
       (1, 1, 'Accusamus hic consequatur similique aut impedit molestias ea.', 'Voluptatem est tenetur ut dolor dolores temporibus officiis. Quia fugit at qui enim voluptatem quibusdam aliquid sed. Minus quia at recusandae id corrupti.', 'Quo animi id officiis ut. Excepturi quisquam est est eveniet reprehenderit. Est doloribus impedit soluta quo impedit. A aliquam ad sint reiciendis.', '2002-03-18'),

 

Testna baza u MongoDB formatu pripremljena je prepisivanjem podataka iz MySQL formata pomoću odgovarajućeg programskog koda VB.NET, navedenog na kraju teksta.  Kao rezultat njegovog izvođenja nastala je kolekcija od 20.000 dokumenata o objavama s uključenim podacima o autorima. Nakon prepisivanja podataka, na kolekciju dokumenata dodana su i dva indeksa kako bi se osigurala podrška u korištenju pomoću sličnih indeksa kakvi postoje u relacijskom modelu.

 

db.posts.createIndex( { pid: -1 } )
db.posts.createIndex( { author_id: -1 } )

 

Na kraju teksta naveden je programski kod za mjerenje brzine izvođenja upita u bazama podataka u oba formata. Mjerenje je izvedeno tako da su u obje opisane baze pomoću odgovarajućih petlji u 100 ponavljanja dodani novi podaci, koji su ažuriranni, a na kraju svakog ciklusa podaci su ponovo obrisani iz baze podataka. Kod relacijske baze korištene su transakcije kako bi se garantiralo izvođenje upita nad svim tablicama u transakciji, dok MongoDB garantira izvođenje operacije nad pojedinačnim dokumentom, bez posebne pripreme transakcije.

 

slika02.png

Slika 2. Testna baza u MySQL formatu može se na kraju postupka izvesti u obliku standardnih SQL naredbi

 

 

slika03.png

Slika 3. Isti podaci prepisani u MongoDB bazu kao kolekcija dokumenata.

 

Rezultati mjerenja prikazani su na sljedećoj slici u odgovarajućem sučelju VB.NET aplikacije. Za svaku vrstu baze podataka napravljeno je po pet mjerenja kako bi se dobili što stvarniji podaci koji uključuju i keširanje podataka te druge slične tehnike u oba modela.

 

slika04.png

Slika 4.  Usporedno mjerenje brzine izvođenja istih operacija na dvije različite baze

 

Iz primjera je vidljivo da ne postoje bitne razlike u brzini izvođenja upita između baza podataka MySQL i MongoDB, bar kad je riječ o modelu podataka iz primjera.

 

Prepisivanje podataka između dvije baze:

    Private Sub btnMySQL2MongoDB_Click(sender As Object, e As EventArgs) Handles btnMySQL2MongoDB.Click
        Dim dbCN As New MySql.Data.MySqlClient.MySqlConnection(dbCS)
        Dim SQLCommand As String = "select p.id, p.author_id, p.title, p.description, p.content, " &
"p.date, a.first_name, a.last_name, a.email, a.birthdate, " &
"a.added " &
                                "from posts p " &
                                "inner join authors a on p.author_id = a.id"
        Dim i As Integer = 0
        Dim client As New MongoClient()
        Dim db = client.GetDatabase("testmongo")
        Dim clist = db.GetCollection(Of Post)("posts")

        Try
            dbCN.Open()
            Dim dbCMD As New MySql.Data.MySqlClient.MySqlCommand(SQLCommand, dbCN)
            Dim dbDR As MySql.Data.MySqlClient.MySqlDataReader = dbCMD.ExecuteReader
            While dbDR.Read()
                Dim p As New Post
                With p
                    .pid = dbDR.Item("id")
                    .author_id = dbDR.Item("author_id")
                    .title = dbDR.Item("title")
                    .description = dbDR.Item("description")
                    .content = dbDR.Item("content")
                    .datee = dbDR.Item("date")
                    .first_name = dbDR.Item("first_name")
                    .last_name = dbDR.Item("last_name")
                    .email = dbDR.Item("email")
                    .birthdate = dbDR.Item("birthdate")
                    .added = dbDR.Item("added")
                End With
                clist.InsertOne(p)
                i += 1
                If i Mod 100 = 0 Then
                    Me.Text = i.ToString : Application.DoEvents()
                End If
            End While
            dbDR.Close()
        Catch Ex As SystemException
            MsgBox(Ex.Message)
        Finally
            If dbCN.State = ConnectionState.Open Then dbCN.Close()
            dbCN.Dispose()
        End Try
    End Sub

 

Mjerenje brzine MySQL:

Private Sub btnTestMySQL_Click(sender As Object, e As EventArgs) Handles btnTestMySQL.Click
        Dim tstart As DateTime = Now

        Dim dbCN As New MySql.Data.MySqlClient.MySqlConnection(dbCS)
        Try
            dbCN.Open()

            For i As Integer = 1 To 100
                Dim SQLCommand As String = "INSERT INTO authors (id, first_name, last_name, email, birthdate, added) VALUES (10001, 'Nenad', 'Crnko', 'Nenad.Crnko@srce.hr', '1981-01-01', '2019-07-01 10:10:10'); "

                SQLCommand += "INSERT INTO posts (id, author_id, title, description, content, date) VALUES (20001, 10001, 'Accusamus hic consequatur similique aut impedit molestias ea.', 'Voluptatem est tenetur ut dolor dolores temporibus officiis. Quia fugit at qui enim voluptatem quibusdam aliquid sed. Minus quia at recusandae id corrupti.', 'Quo animi id officiis ut. Excepturi quisquam est est eveniet reprehenderit. Est doloribus impedit soluta quo impedit. A aliquam ad sint reiciendis.', '2019-07-01'); "

                SQLCommand += "update posts set date = '2019-07-02' where id = 20001; "
                SQLCommand += "update posts set date = '2019-07-03' where author_id = 10001; "

                SQLCommand = "delete from posts where id = 20001; "
                SQLCommand += "delete from authors where id = 10001; "

                Dim dbTransaction As MySql.Data.MySqlClient.MySqlTransaction
                dbTransaction = dbCN.BeginTransaction(IsolationLevel.ReadCommitted)
                Dim dbCMD As New MySql.Data.MySqlClient.MySqlCommand(SQLCommand, dbCN)

                With dbCMD
                    .Connection = dbCN
                    .CommandType = CommandType.Text
                    .CommandTimeout = 30
                    .Transaction = dbTransaction
                    .CommandText = SQLCommand
                    .ExecuteNonQuery()
                End With
                dbTransaction.Commit()

                SQLCommand = "delete from posts where id = 20001; "
                SQLCommand = "delete from authors where id = 10001; "

                dbTransaction = dbCN.BeginTransaction(IsolationLevel.ReadCommitted)
                With dbCMD
                    .Connection = dbCN
                    .Transaction = dbTransaction
                    .CommandText = SQLCommand
                    .ExecuteNonQuery()
                End With
                dbTransaction.Commit()

            Next

        Catch Ex As SystemException
            MsgBox(Ex.Message, MsgBoxStyle.Exclamation, "Upozorenje")

        Finally
            If dbCN.State = ConnectionState.Open Then dbCN.Close()
            dbCN.Dispose()
        End Try

        Dim tend As DateTime = Now
        Dim tdiff As TimeSpan = tend - tstart
        lstDocuments.Items.Add("MySQL - vrijeme izvođenja: " + tdiff.TotalMilliseconds.ToString)

    End Sub

 

Mjerenje brzine MongoDB:

Private Sub btnTestMongo_Click(sender As Object, e As EventArgs) Handles btnTestMongo.Click
        Dim tstart As DateTime = Now

        Dim client As New MongoClient()
        Try
            Dim db = client.GetDatabase("testmongo")
            Dim clist = db.GetCollection(Of Post)("posts")

            For i As Integer = 1 To 100

                Dim p As New Post
                With p
                    .pid = 20001
                    .author_id = 10001
                    .title = "accusamus hic consequatur similique aut impedit molestias ea."
                    .description = "voluptatem est tenetur ut dolor dolores temporibus officiis. quia fugit at qui enim voluptatem quibusdam aliquid sed. minus quia at recusandae id corrupti."
                    .content = "quo animi id officiis ut. excepturi quisquam est est eveniet reprehenderit. est doloribus impedit soluta quo impedit. a aliquam ad sint reiciendis."
                    .datee = "2019-07-01"
                    .first_name = "nenad"
                    .last_name = "crnko"
                    .email = "nenad.crnko@srce.hr"
                    .birthdate = "1981-01-01"
                    .added = "2019-07-01 10:10:10"
                End With
                clist.InsertOne(p)

                Dim filter_update1 As BsonDocument = New BsonDocument("pid", "20001")
                clist.UpdateOne(filter_update1, New BsonDocument("$set", New BsonDocument("datee", "2019-07-02")))

                Dim filter_update2 As BsonDocument = New BsonDocument("author_id", "10001")
                clist.UpdateOne(filter_update2, New BsonDocument("$set", New BsonDocument("datee", "2019-07-03")))

                Dim filter_delete As BsonDocument = New BsonDocument("pid", "20001")
                clist.DeleteOne(filter_delete)

            Next

        Catch Ex As SystemException
            MsgBox(Ex.Message, MsgBoxStyle.Exclamation, "Upozorenje")

        End Try

        Dim tend As DateTime = Now
        Dim tdiff As TimeSpan = tend - tstart
        lstDocuments.Items.Add("MongoDB - vrijeme izvođenja: " + tdiff.TotalMilliseconds.ToString)

    End Sub

Kategorija