Czyta MySQL vs MongoDB 1000


320

Byłem bardzo podekscytowany MongoDb i testowałem go ostatnio. Miałem tabelę o nazwie posty w MySQL z około 20 milionami rekordów indeksowanych tylko w polu o nazwie „id”.

Chciałem porównać prędkość z MongoDB i przeprowadziłem test, który losowo pobrałby i wydrukował 15 rekordów z naszych ogromnych baz danych. Uruchomiłem zapytanie około 1000 razy dla mysql i MongoDB i jestem zaskoczony, że nie zauważam dużej różnicy prędkości. Może MongoDB jest 1,1 razy szybszy. To bardzo rozczarowujące. Czy coś robię źle? Wiem, że moje testy nie są idealne, ale MySQL jest na równi z MongoDb, jeśli chodzi o czytanie intensywnych obowiązków.


Uwaga:

  • Mam podwójny rdzeń + (2 wątki) i7 procesor i 4 GB RAM
  • Mam 20 partycji na MySQL, każdy z 1 milionem rekordów

Przykładowy kod używany do testowania MongoDB

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$time_taken = 0;
$tries = 100;
// connect
$time_start = microtime_float();

for($i=1;$i<=$tries;$i++)
{
    $m = new Mongo();
    $db = $m->swalif;
    $cursor = $db->posts->find(array('id' => array('$in' => get_15_random_numbers())));
    foreach ($cursor as $obj)
    {
        //echo $obj["thread_title"] . "<br><Br>";
    }
}

$time_end = microtime_float();
$time_taken = $time_taken + ($time_end - $time_start);
echo $time_taken;

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000) ;

    }
    return $numbers;
}

?>


Przykładowy kod do testowania MySQL

<?php
function microtime_float()
{
    list($usec, $sec) = explode(" ", microtime());
    return ((float)$usec + (float)$sec);
}
$BASE_PATH = "../src/";
include_once($BASE_PATH  . "classes/forumdb.php");

$time_taken = 0;
$tries = 100;
$time_start = microtime_float();
for($i=1;$i<=$tries;$i++)
{
    $db = new AQLDatabase();
    $sql = "select * from posts_really_big where id in (".implode(',',get_15_random_numbers()).")";
    $result = $db->executeSQL($sql);
    while ($row = mysql_fetch_array($result) )
    {
        //echo $row["thread_title"] . "<br><Br>";
    }
}
$time_end = microtime_float();
$time_taken = $time_taken + ($time_end - $time_start);
echo $time_taken;

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000);

    }
    return $numbers;
}
?>

11
Jakie są rzeczywiste czasy?
Abe Petrillo

30
Nie jestem DBA, więc jest to komentarz, a nie odpowiedź, ale szybkość nie powinna być głównym czynnikiem przy wyborze między MySQL i MongoDB. Rzeczy takie jak schemat bez schematu (tj. Jak często schemat danych musi się zmieniać) i skalowanie rozmiaru (tj. Jak łatwo jest podzielić dane tak, że typowy odczyt wymaga danych tylko z jednego serwera) są ważniejsze przy wyborze lubię to.
rossdavidh

17
Jak może być szybszy w czytaniu? Czyta z urządzenia mechanicznego. Taki sam jak MySQL. Zależy to od prędkości samego urządzenia, nie możesz użyć jakiejś dziwnej magii za pomocą kodu, aby przełamać ograniczenia sprzętowe.
NB

7
To pytanie przypomina mi o tym: mongodb-is-web-scale.com
oligofren

13
Ludzie mylą się, że czują, że poszliby z jednym lub drugim. W kuchni będziesz potrzebować zarówno kuchenki mikrofalowej, jak i piekarnika. Po prostu nie możesz powiedzieć, że użyję tylko jednego lub drugiego. Przypadki użycia dla obu systemów są różne. Jeśli potrzebujesz ACID dla części aplikacji, skorzystaj z RDBMS, jeśli nie zależy ci na spójności i ograniczeniach, a twoje encje mogą być przechowywane jako wszystko w jednym (kolekcje), użyj MongoDB. Skończysz na systemie hybrydowym, kluczowym punktem jest decyzja, gdzie przechowywać.
Teoman shipahi

Odpowiedzi:


645

MongoDB nie jest magicznie szybszy. Jeśli przechowujesz te same dane, uporządkowane zasadniczo w ten sam sposób i uzyskujesz do nich dostęp w dokładnie taki sam sposób, to naprawdę nie powinieneś oczekiwać, że Twoje wyniki będą zupełnie inne. W końcu zarówno MySQL, jak i MongoDB są GPL, więc jeśli Mongo miał w sobie jakiś magicznie lepszy kod IO, zespół MySQL mógłby po prostu włączyć go do swojej bazy kodów.

Ludzie widzą rzeczywistą wydajność MongoDB głównie dlatego, że MongoDB pozwala na zapytania w inny sposób, który jest bardziej odpowiedni dla twojego obciążenia.

Rozważmy na przykład projekt, który zawierał wiele informacji o skomplikowanej jednostce w znormalizowany sposób. Może to z łatwością wykorzystać dziesiątki tabel w MySQL (lub dowolnym relacyjnym pliku db) do przechowywania danych w normalnej formie, z wieloma indeksami potrzebnymi do zapewnienia relacyjnej integralności między tabelami.

Teraz rozważ ten sam projekt z magazynem dokumentów. Jeśli wszystkie powiązane tabele są podrzędne w stosunku do tabeli głównej (a często tak jest), być może uda się modelować dane w taki sposób, że cała jednostka jest przechowywana w jednym dokumencie. W MongoDB możesz przechowywać to jako pojedynczy dokument, w jednej kolekcji. To tutaj MongoDB zaczyna zapewniać doskonałą wydajność.

W MongoDB, aby odzyskać cały byt, musisz wykonać:

  • Jedno wyszukiwanie indeksu w kolekcji (przy założeniu, że jednostka jest pobierana przez identyfikator)
  • Pobierz zawartość jednej strony bazy danych (rzeczywisty binarny dokument json)

Więc wyszukiwanie b-drzewa i odczyt strony binarnej. Log (n) + 1 IO. Jeśli indeksy mogą znajdować się całkowicie w pamięci, to 1 IO.

W MySQL z 20 tabelami musisz wykonać:

  • Jedno wyszukiwanie indeksu w tabeli głównej (ponownie, zakładając, że jednostka jest pobierana przez identyfikator)
  • Dzięki indeksowi klastrowemu możemy założyć, że wartości dla wiersza głównego znajdują się w indeksie
  • Ponad 20 wyszukiwań zakresu (miejmy nadzieję na indeksie) dla wartości pk encji
  • Prawdopodobnie nie są to indeksy klastrowe, więc te same ponad 20 wyszukiwań danych, gdy ustalimy, jakie są odpowiednie wiersze podrzędne.

Tak więc suma dla mysql, nawet przy założeniu, że wszystkie indeksy są w pamięci (co jest trudniejsze, ponieważ jest ich 20 razy więcej) wynosi około 20 wyszukiwań zakresu.

Te wyszukiwania zakresów prawdopodobnie składają się z przypadkowych operacji we / wy - różne tabele z pewnością będą znajdować się w różnych miejscach na dysku, i możliwe jest, że różne wiersze w tym samym zakresie w tej samej tabeli dla jednostki mogą nie być ciągłe (w zależności od tego, jak jednostka była zaktualizowane itp.).

Tak więc w tym przykładzie końcowa suma to około 20 razy więcej IO z MySQL na logiczny dostęp, w porównaniu do MongoDB.

W ten sposób MongoDB może zwiększyć wydajność w niektórych przypadkach użycia .


43
co jeśli po prostu umieścimy jeden główny stół w mysql?
ariso

98
@ariso: Jest to optymalizacja przez denormalizację. Może zapewnić wzrost wydajności. Jeśli jednak to zrobisz, wyrzucisz swój czysty projekt i całą moc (nie wspominając o większości funkcji) relacyjnej bazy danych. I to działa naprawdę, dopóki nie osiągniesz limitu kolumny.
Sean Reilly

7
@SeanReilly Twój przykład z encjami (powinien być edytowany z obiektami, nie ma programowania zorientowanego na encje :)) jest nieprawidłowy. Jak powiedziało ariso, można serializować obiekt i przechowywać go w bazie danych i deserializować w razie potrzeby (dowolna forma serializacji). Prawdziwa moc trwałych obiektów jest utrzymywana w systemach db oodbms, a nie documnet db. Ale zgadzam się, że każdy ma swój własny cel i mocne strony (ale twój przykład bardziej zaciemnia wizję i trafność tego tematu).
Geo C.

9
Powiedziałbym, że 20 dołączeń nie jest najlepszym zapytaniem w najlepszym schemacie bazy danych.
Audrius Meskauskas

8
@SeanReilly Uważam, że twój przykład jest bardzo pomocny. Możesz zbudować specjalny interfejs MySQL, który automatycznie serializuje i deserializuje obiekty do tabel i zachowuje się tak, jak robi to mongodb. Ale dlaczego nie użyć po prostu czegoś specjalnie zaprojektowanego do takiego zastosowania? Także twoje użycie „bytu” ma sens. Chodzi o to, że organizujesz dane jako dokumenty, a nie pola w tabeli. To, czy dokument jest obiektem złożonym w języku OO, nie ma znaczenia w tym przykładzie.
BHS

57

Czy masz współbieżność, tzn. Równoczesnych użytkowników? Jeśli uruchomisz 1000 razy zapytanie prosto z jednym wątkiem, nie będzie prawie żadnej różnicy. Zbyt łatwe dla tych silników :)

ALE zdecydowanie sugeruję, abyś zbudował prawdziwą sesję testowania obciążenia, co oznacza użycie wtryskiwacza takiego jak JMeter z 10, 20 lub 50 użytkownikami W TYM SAMYM CZASIE, aby naprawdę zobaczyć różnicę (spróbuj osadzić ten kod na stronie internetowej JMeter można zapytać).

Właśnie to zrobiłem dzisiaj na jednym serwerze (i prostej kolekcji / tabeli), a wyniki są dość interesujące i zaskakujące (MongoDb był naprawdę szybszy w zapisach i odczytach, w porównaniu do silnika MyISAM i silnika InnoDb).

To naprawdę powinno być częścią twojego testu: współbieżność i silnik MySQL. W związku z tym potrzeby w zakresie projektowania danych / schematów i aplikacji mają ogromne wymagania, wykraczające poza czas reakcji. Daj mi znać, gdy otrzymasz wyniki. Potrzebuję również informacji na ten temat!


42
Czy możesz podzielić się wynikami?
Imran Omar Bukhsh,

1
Tak, wyniki w tym zakresie będą bardzo pomocne
Vasil Popov

3
Na pewno to by się po prostu skalowało ... gdyby to były jabłka do jabłek, tak jak mówiono w pozostałej części tego tematu. Więc jeśli na avg wykonuje x, teraz symuluj z wielu źródeł, wyjaśnij, dlaczego mongo byłoby szybsze. tzn. powiedzmy po prostu ze względu na zgodę, że mysql był na średniej szybszy dla pojedynczego żądania ... dlaczego mongo stałoby się szybsze dla wielu? Nie uważam tego za bardzo naukowe. Mówię, że test jest ważny .. ale nie jestem pewien, jak różnica byłaby ogromna, gdybyś porównał Jabłka do Jabłek, jak wyjaśniono w pozostałej części tematu.
Seabizkit

36

Źródło: https://github.com/webcaetano/mongo-mysql

10 rzędów

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms

100 rzędów

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms

1000 rzędów

mysql insert: 94813ms (1.58 minutes)
mysql select: 13ms

mongo insert: 1013ms
mongo select: 677ms

10.000 rzędów

mysql insert: 924695ms (15.41 minutes)
mysql select: 144ms

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)

91
15 minut, aby wstawić 10 000 wierszy? To bardzo anemiczna baza danych MySQL. Z mojego doświadczenia wynika, że ​​jeśli taka operacja zbliża się do 1 s, mój telefon zapala się ze skargami. :)
Mordechai,

1
Xtreme Biker spójrz na link. Test opublikowałem od innych osób z innymi ustawieniami.
user2081518,

14
Kilka punktów: 1) Mysql musi zostać zoptymalizowany i odpowiednio skonfigurowany, istnieje wiele różnych sposobów wstawiania dużych ilości danych, a właściwie wykonane może zająć 0,1% z 15 minut, zobacz na przykład tę stronę . 2) MongoDB nie zapisuje od razu danych na dysku, dlatego „szybciej” wygląda, ale jeśli komputer ulegnie awarii, dane zostaną utracone. 3) Czytanie jest znacznie szybsze w MySQL
elipoultorak

81
15 minut dla 10.000 wierszy? Wpisałeś każdy wiersz? =))))
Iurie Manea

6
każdy, kto uważa, że ​​wstawienie dziesięciu wierszy do mysql zajmuje 1,7 sekundy, zasługuje na ból, jaki
odczuwają

20

man ,,, odpowiedź jest taka, że ​​w zasadzie testujesz PHP, a nie bazę danych.

nie zawracaj sobie głowy powtarzaniem wyników, komentując wydruk, czy nie. jest kawał czasu.

   foreach ($cursor as $obj)
    {
        //echo $obj["thread_title"] . "<br><Br>";
    }

podczas gdy druga część spędza na zrywaniu szeregu liczb randowych.

function get_15_random_numbers()
{
    $numbers = array();
    for($i=1;$i<=15;$i++)
    {
        $numbers[] = mt_rand(1, 20000000) ;

    }
    return $numbers;
}

wtedy jest zasadnicza różnica między implodami czarno-białymi i cewkami.

i wreszcie co się tutaj dzieje. wygląda jak tworzenie połączenia za każdym razem, a zatem jego testowanie czasu połączenia plus czasu zapytania.

$m = new Mongo();

vs

$db = new AQLDatabase();

więc twoje 101% szybsze może okazać się 1000% szybsze dla podstawowego zapytania pozbawionego jazzu.

urghhh.


4
Oczywiście praktyka kodowania może mieć duże znaczenie w każdej sytuacji, ale nie jest to specyficzne dla żadnego rodzaju języka, interfejsu API ani rozszerzenia. generowanie liczb losowych przed uruchomieniem timera będzie miało znaczenie, ale większość czasu w tym procesie nie ma wątpliwości na podstawie transakcji w bazie danych. generowanie liczb losowych jest banalne, bazy danych SQL i NoSQL nie.
JSON

1
nie wybieraj numeru rand. najwyraźniej za każdym razem brakowało połączenia. wszystkie problemy składają się na testowanie czegoś innego niż zamierzone.
Gabe Rainbow

2
Nie, nie przegapiłem tego. MySQL nie zamknie połączenia, dopóki skrypt się nie skończy, chyba że zostanie wywołana mysqli_close (). W przeciwnym razie powtarzanie wywołań funkcji mysqli_connect () spowoduje tylko pobranie istniejącego zasobu mysql z bieżącej tabeli zasobów, a nie wykonanie nowej procedury połączenia. Nie jestem do końca pewien, czym jest obiekt AQLDatabase, ale jeśli używa lib mysql (co prawdopodobnie robi), będzie miał takie samo zachowanie. Rozszerzenie MongoDB używa puli połączeń, więc ta sama podstawowa rzecz występuje podczas tworzenia „połączenia” mongodb więcej niż raz w skrypcie.
JSON

Zgadzam się, że jego test porównawczy mógł zostać wykonany inaczej, ale odzwierciedla te same podstawowe wyniki, co inne ławki MySQL vs Mongo, które widziałem. Mongo jest zwykle szybszy podczas wstawiania (znacznie szybszy w przypadku prostszych wstawek), a MySQL jest zwykle szybszy podczas wybierania.
JSON

wprawdzie byłem zbyt gburowaty; właśnie ten ciąg html „<br>” naprawdę mnie „zachęcił”. nie potrzebujesz ładnego druku w testach. nawet iteracja wydaje się być testem php, a nie testem bazy danych. ogólnie rzecz biorąc, ta baza danych AQL „prawdopodobnie / może” moment… więcej składników oznacza więcej niewiadomych.
Gabe Rainbow,

17

https://github.com/reoxey/benchmark

reper

porównanie prędkości MySQL i MongoDB w GOLANG 1.6 i PHP5

system zastosowany do testu porównawczego: DELL cpu i5 4. generacji 1.70 Ghz * 4 ram 4 GB GPU ram 2 GB

Porównanie prędkości RDBMS w porównaniu z NoSQL dla INSERT, SELECT, UPDATE, DELETE wykonujących różną liczbę wierszy 10 100,1000,10000,100000,1000000

Językiem używanym do wykonania jest: PHP5 i najszybszy język Google GO 1.6

________________________________________________
GOLANG with MySQL (engine = MyISAM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      1.195444ms
100                     6.075053ms
1000                    47.439699ms
10000                   483.999809ms
100000                  4.707089053s
1000000                 49.067407174s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 872.709µs


        SELECT & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 20.717354746s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 2.309209968s
100000                  257.411502ms
10000                   26.73954ms
1000                    3.483926ms
100                     915.17µs
10                      650.166µs


            DELETE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 6.065949ms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


________________________________________________
GOLANG with MongoDB
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      2.067094ms
100                     8.841597ms
1000                    106.491732ms
10000                   998.225023ms
100000                  8.98172825s
1000000                 1m 29.63203158s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 5.251337439s


        FIND & DISPLAY (with index declared)
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 21.540603252s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1                       1.330954ms
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

________________________________________________
PHP5 with MySQL (engine = MyISAM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
 10                     0.0040680000000001s
 100                    0.011595s
 1000                   0.049718s
 10000                  0.457164s
 100000                 4s
 1000000                42s


            SELECT
------------------------------------------------
num of rows             time taken
------------------------------------------------
 1000000                <1s


            SELECT & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
  1000000               20s
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

________________________________________________
PHP5 with MongoDB 
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            INSERT
------------------------------------------------
num of rows             time taken
------------------------------------------------
10                      0.065744s
100                     0.190966s
1000                    0.2163s
10000                   1s
100000                  8s
1000000                 78s


            FIND
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 <1s


            FIND & DISPLAY
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 7s


            UPDATE
------------------------------------------------
num of rows             time taken
------------------------------------------------
1000000                 9s

myisam nie jest innodb, która wersja mongodb i silnik pamięci?

1
ważne jest, aby określić wersje MySQL i MongoDB.
Miron

1
Nie używaj MyISAM. Używaj wkładek wsadowych!
Rick James

MySQL jest szybszy niż Mongodb w zapytaniu Wstaw ?! wydaje się to nieprawdą, dopóki mysql nie będzie musiał przygotować kolumn i relacji. mysql select jest szybszy niż mongodb select, ale w zapytaniu wstawiania mongo jest szybszy
Exind

6

Oto kilka badań, które badały RDBMS vs NoSQL przy użyciu MySQL vs Mongo, wnioski były zgodne z odpowiedzią @Sean Reilly. Krótko mówiąc, korzyści płyną z projektu, a nie z pewnej różnicy prędkości. Wniosek na stronie 35–36:

RDBMS vs NoSQL: Porównanie wydajności i skalowania

W ramach projektu przetestowano, przeanalizowano i porównano wydajność i skalowalność dwóch typów baz danych. Przeprowadzone eksperymenty obejmowały uruchomienie różnych liczb i typów zapytań, niektóre bardziej złożone niż inne, w celu przeanalizowania skalowania baz danych przy zwiększonym obciążeniu. Najważniejszym czynnikiem w tym przypadku był typ zapytania użyty, ponieważ MongoDB mógł szybciej obsługiwać bardziej złożone zapytania, głównie ze względu na jego prostszy schemat przy poświęceniu duplikacji danych, co oznacza, że ​​baza danych NoSQL może zawierać duże ilości duplikatów danych. Chociaż można zastosować schemat migrowany bezpośrednio z RDBMS, wyeliminowałoby to przewagę bazowej reprezentacji danych w dokumentach podrzędnych MongoDB, co pozwoliło na użycie mniejszej liczby zapytań do bazy danych podczas łączenia tabel.Pomimo wzrostu wydajności, który MongoDB miał nad MySQL w tych złożonych zapytaniach, kiedy test porównawczy modelował zapytanie MySQL podobnie do złożonego zapytania MongoDB przy użyciu zagnieżdżonych SELECT MySQL działało najlepiej, chociaż przy większej liczbie połączeń oba zachowywały się podobnie. Ostatni typ testu porównawczego zapytania, który był złożonym zapytaniem zawierającym dwa JOINS i podkwerendę, pokazał przewagę MongoDB nad MySQL ze względu na użycie poddokumentów. Ta zaleta wiąże się z kosztem duplikacji danych, co powoduje wzrost wielkości bazy danych. Jeśli takie zapytania są typowe dla aplikacji, ważne jest rozważenie baz danych NoSQL jako alternatywy, biorąc pod uwagę koszty przechowywania i rozmiar pamięci wynikające z większego rozmiaru bazy danych.


-6

Na pojedynczym serwerze MongoDb nie byłby szybszy niż mysql MyISAM zarówno do odczytu, jak i zapisu, biorąc pod uwagę, że rozmiary tabel / dokumentów są małe od 1 GB do 20 GB.
MonoDB będzie szybszy w przypadku Parallel Reduce w klastrach z wieloma węzłami, w których Mysql NIE może skalować się w poziomie.


5
Czy możesz podać jakieś dowody lub więcej szczegółów na poparcie tego?
Steve Westbrook

Nie można skalować w poziomie? Co z NDB? DRBD wspiera MySQL?
Ernestas,

To nie jest prawda. MongoDB ma limit dokumentów 16MD. MySQL może mieć znacznie więcej, jeśli chcesz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.