MySQL vs MongoDB 1000 lit

321

J'ai été très enthousiasmé par MongoDb et je l'ai testé récemment. J'avais une table appelée posts dans MySQL avec environ 20 millions d'enregistrements indexés uniquement sur un champ appelé 'id'.

Je voulais comparer la vitesse avec MongoDB et j'ai exécuté un test qui permettrait d'obtenir et d'imprimer 15 enregistrements au hasard à partir de nos énormes bases de données. J'ai exécuté la requête environ 1 000 fois chacune pour mysql et MongoDB et je suis surpris de ne pas remarquer beaucoup de différence de vitesse. Peut-être que MongoDB est 1,1 fois plus rapide. C'est très décevant. Y a-t-il quelque chose que je fais mal? Je sais que mes tests ne sont pas parfaits mais MySQL est à égalité avec MongoDb quand il s'agit de lire des tâches intensives.


Remarque:

  • J'ai dual core + (2 threads) i7 cpu et 4GB ram
  • J'ai 20 partitions sur MySQL chacune de 1 million d'enregistrements

Exemple de code utilisé pour tester 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;
}

?>


Exemple de code pour tester 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;
}
?>
Imran Omar Bukhsh
la source
11
Quels sont les temps réels?
Abe Petrillo
30
Je ne suis pas un DBA, c'est donc un commentaire et non une réponse, mais la vitesse ne devrait pas être la principale considération lors du choix entre MySQL et MongoDB. Des éléments tels que le schéma sans schéma ou le schéma (c'est-à-dire à quelle fréquence votre schéma de données doit-il changer) et la mise à l'échelle (c'est-à-dire comment est-il facile de partager vos données afin qu'une lecture typique nécessite des données provenant d'un seul serveur) sont plus importants pour un choix comme ça.
rossdavidh
17
Comment peut-il être plus rapide en lecture? Il lit à partir d'un appareil mécanique. Identique à MySQL. Cela dépend de la vitesse de l'appareil lui-même, vous ne pouvez pas utiliser de magie étrange via le code afin de briser les limites du matériel.
NB
7
Cette question me rappelle juste ceci: mongodb-is-web-scale.com
oligofren
13
Les gens se trompent en pensant qu'ils iraient avec l'un ou l'autre. Vous aurez besoin d'un four à micro-ondes et d'un four dans votre cuisine. Vous ne pouvez pas dire que je n'utiliserai que l'un ou l'autre. Les cas d'utilisation pour les deux systèmes sont différents. Si vous avez besoin d'ACID pour une partie de votre application, utilisez alors RDBMS, si vous ne vous souciez pas de la cohérence et des contraintes et que vos entités peuvent être stockées en une seule (collections), utilisez alors MongoDB. Vous finirez par utiliser un système hybride, le point clé est de décider quoi stocker où.
Teoman shipahi

Réponses:

647

MongoDB n'est pas magiquement plus rapide. Si vous stockez les mêmes données, organisées essentiellement de la même manière, et y accédez exactement de la même manière, alors vous ne devriez vraiment pas vous attendre à ce que vos résultats soient extrêmement différents. Après tout, MySQL et MongoDB sont tous deux GPL, donc si Mongo avait du code IO magiquement meilleur, alors l'équipe MySQL pourrait simplement l'incorporer dans leur base de code.

Les gens voient les performances de MongoDB dans le monde réel en grande partie parce que MongoDB vous permet d'interroger d'une manière différente qui est plus sensible à votre charge de travail.

Par exemple, considérons une conception qui a persisté beaucoup d'informations sur une entité compliquée de manière normalisée. Cela pourrait facilement utiliser des dizaines de tables dans MySQL (ou n'importe quelle base de données relationnelle) pour stocker les données sous forme normale, avec de nombreux index nécessaires pour assurer l'intégrité relationnelle entre les tables.

Considérez maintenant la même conception avec un magasin de documents. Si toutes ces tables associées sont subordonnées à la table principale (et elles le sont souvent), vous pourrez peut-être modéliser les données de sorte que l'entité entière soit stockée dans un seul document. Dans MongoDB, vous pouvez stocker cela en tant que document unique, dans une seule collection. C'est là que MongoDB commence à offrir des performances supérieures.

Dans MongoDB, pour récupérer l'entité entière, vous devez effectuer:

  • Une recherche d'index sur la collection (en supposant que l'entité est récupérée par id)
  • Récupérer le contenu d'une page de base de données (le document json binaire réel)

Donc une recherche de b-tree, et une page binaire lue. Log (n) + 1 E / S. Si les index peuvent résider entièrement en mémoire, alors 1 E / S.

Dans MySQL avec 20 tables, vous devez effectuer:

  • Une recherche d'index sur la table racine (encore une fois, en supposant que l'entité est récupérée par id)
  • Avec un index clusterisé, nous pouvons supposer que les valeurs de la ligne racine sont dans l'index
  • Plus de 20 recherches de plage (si tout va bien sur un indice) pour la valeur pk de l'entité
  • Ce ne sont probablement pas des index clusterisés, donc les mêmes 20+ recherches de données une fois que nous avons déterminé quelles sont les lignes enfants appropriées.

Donc, le total pour mysql, même en supposant que tous les index sont en mémoire (ce qui est plus difficile car il y en a 20 fois plus) est d'environ 20 recherches de plage.

Ces recherches de plage sont probablement composées d'E / S aléatoires - différentes tables résideront certainement à différents endroits sur le disque, et il est possible que différentes lignes de la même plage dans la même table pour une entité ne soient pas contiguës (selon la façon dont l'entité a été mis à jour, etc.).

Donc, pour cet exemple, le décompte final est environ 20 fois plus d'E / S avec MySQL par accès logique, par rapport à MongoDB.

C'est ainsi que MongoDB peut augmenter les performances dans certains cas d'utilisation .

Sean Reilly
la source
43
que se passe-t-il si nous mettons juste une table principale dans mysql?
ariso
99
@ariso: C'est l'optimisation par dénormalisation. Il peut fournir une amélioration des performances. Cependant, si vous faites cela, vous jetez votre design épuré et toute la puissance (sans parler de la plupart des fonctionnalités) d'une base de données relationnelle. Et cela ne fonctionne vraiment que jusqu'à ce que vous atteigniez la limite de colonne.
Sean Reilly
7
@SeanReilly Votre exemple avec des entités (devrait être édité avec des objets, il n'y a pas de programmation orientée entité :)) n'est pas valide. Comme l'a dit ariso, vous pouvez sérialiser un objet et le stocker dans la base de données et désérialiser en cas de besoin (toute forme de sérialisation). La véritable puissance des objets persistants est détenue dans les systèmes oodbms et non documnet db. Mais je suis d'accord que chacun a son propre but et ses forces (mais votre exemple obscurcit davantage la vision et la pertinence de ce sujet).
Geo C.
9
20 jointures, je dirais, n'est probablement pas la meilleure requête sur le meilleur schéma de base de données possible.
Audrius Meskauskas
8
@SeanReilly J'ai trouvé votre exemple très utile. Vous pouvez créer une interface spéciale pour MySQL qui sérialise et désérialise automatiquement les objets en tables et se comporte comme le fait mongodb. Mais alors, pourquoi ne pas simplement utiliser quelque chose spécialement conçu pour être utilisé de cette façon? Votre utilisation de "l'entité" a également un sens. Le fait est que vous organisez les données sous forme de documents plutôt que sous forme de champs dans un tableau. Que le document soit ou non un objet composé dans un langage OO est sans importance pour l'exemple.
BHS
57

Avez-vous des accès concurrents, c'est-à-dire des utilisateurs simultanés? Si vous exécutez simplement 1000 fois la requête directement, avec un seul thread, il n'y aura presque aucune différence. Trop facile pour ces moteurs :)

MAIS je vous suggère fortement de créer une véritable session de test de charge, ce qui signifie utiliser un injecteur tel que JMeter avec 10, 20 ou 50 utilisateurs EN MÊME TEMPS afin que vous puissiez vraiment voir une différence (essayez d'incorporer ce code dans une page Web JMeter pourrait interroger).

Je viens de le faire aujourd'hui sur un seul serveur (et une simple collection / table) et les résultats sont assez intéressants et surprenants (MongoDb était vraiment plus rapide en écriture et en lecture, par rapport au moteur MyISAM et au moteur InnoDb).

Cela devrait vraiment faire partie de votre test: moteur d'accès simultané et MySQL. Ensuite, les besoins de conception / application de données / schémas sont bien sûr des exigences énormes, au-delà des temps de réponse. Faites-moi savoir lorsque vous obtenez des résultats, j'ai également besoin de commentaires à ce sujet!

theAndroid
la source
42
Pouvez-vous partager vos résultats?
Imran Omar Bukhsh
1
Ya, les résultats à ce sujet seront très utiles
Vasil Popov
3
Certes, cela ne ferait que changer d'échelle ... s'il s'agissait de pommes à pommes comme ils l'ont dit dans le reste de ce sujet. Donc, si sur avg il exécute x, simulez maintenant à partir de plusieurs sources, veuillez expliquer pourquoi mongo serait plus rapide. c'est-à-dire, disons simplement par accord que mysql était en moyenne plus rapide pour une seule demande ... pourquoi mongo deviendrait-il maintenant plus rapide pour plusieurs? Je ne trouve pas cela très scientifique. Je dis que le test est valide .. mais je ne sais pas trop comment la différence serait énorme si vous compariez des pommes aux pommes comme le reste du sujet l'explique.
Seabizkit
35

Source: https://github.com/webcaetano/mongo-mysql

10 rangées

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms

100 rangées

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms

1000 lignes

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

mongo insert: 1013ms
mongo select: 677ms

10.000 lignes

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

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)
user2081518
la source
91
15 min pour insérer 10 000 lignes? C'est une base de données MySQL très anémique. D'après mon expérience, si une telle opération approche de 1 seconde, mon téléphone s'allume de plaintes. :)
Mordechai
1
Xtreme Biker jetez un oeil sur le lien. J'ai posté le test d'autres personnes avec d'autres paramètres.
user2081518
14
Quelques points: 1) Mysql doit être optimisé et configuré correctement, il existe de nombreuses façons différentes d'insérer de grandes quantités de données, et fait correctement, cela peut prendre 0,1% des 15 minutes, voir cette page par exemple. 2) MongoDB n'écrit pas les données sur le disque immédiatement, c'est pourquoi il "semble" plus rapide, mais si votre ordinateur tombe en panne, les données sont perdues. 3) La lecture est beaucoup plus rapide dans MySQL
elipoultorak
81
15min pour 10.000 lignes? Vous avez tapé chaque ligne? =))))
Iurie Manea
7
quiconque croit qu'une affirmation selon laquelle il faut 1,7 seconde pour insérer dix lignes dans mysql mérite la douleur qu'ils ressentent de la part de mongo
John Haugeland
20

man ,,, la réponse est que vous testez essentiellement PHP et non une base de données.

ne vous embêtez pas à répéter les résultats, que vous commentiez l'impression ou non. il y a beaucoup de temps.

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

tandis que l'autre morceau est de passer un tas de numéros de rand.

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

    }
    return $numbers;
}

puis il y a une différence majeure n / b imploser et en.

et enfin ce qui se passe ici. ressemble à créer une connexion à chaque fois, testant ainsi le temps de connexion plus le temps de requête.

$m = new Mongo();

contre

$db = new AQLDatabase();

donc votre 101% plus rapide pourrait s'avérer 1000% plus rapide pour la requête sous-jacente dépouillée de jazz.

urghhh.

Gabe Rainbow
la source
4
naturellement, la pratique du codage peut faire une grande différence dans n'importe quelle situation, mais ce n'est pas spécifique à tout type de langage, d'api ou d'extension. générer des nombres aléatoires avant de démarrer la minuterie fera une différence, mais la majorité du temps dans le processus provient sans aucun doute des transactions de la base de données. la génération de nombres aléatoires est triviale, les bases de données SQL et NoSQL ne le sont pas.
JSON
1
ne choisissez pas le nombre de rand. vous avez clairement raté la création de connexion à chaque fois. tous les problèmes s'additionnent pour tester autre chose que prévu.
Gabe Rainbow
2
Non, je ne l'ai pas manqué. MySQL ne fermera pas la connexion jusqu'à la fin du script, sauf si mysqli_close () est appelé. Sinon, répéter les appels à mysqli_connect () ne tirera que la ressource mysql existante de la table de ressources actuelle, plutôt que de valider une nouvelle procédure de connexion. Je ne suis pas exactement sûr de ce qu'est l'objet AQLDatabase, mais s'il utilise la bibliothèque mysql (ce qu'il fait probablement), il aura le même comportement. L'extension MongoDB utilise le regroupement de connexions, donc la même chose de base se produit lors de la création d'une 'connexion' mongodb plus d'une fois dans un script.
JSON
Je suis d'accord que son benchmark aurait pu être fait différemment, mais il reflète les mêmes résultats de base que les autres bancs MySQL vs Mongo que j'ai vus. Mongo est généralement plus rapide lors de l'insertion (beaucoup plus rapide pour les insertions plus simples) et MySQL est généralement plus rapide lors de la sélection.
JSON
certes, j'étais trop bourru; c'est cette chaîne html concat de "<br>" qui m'a vraiment "poussé". vous n'avez pas besoin d'une jolie impression dans les tests. même l'itérer semble être un test php et non un test de base de données. dans l'ensemble, ce moment «éventuellement / peut-être» d'AQLDatabase ... plus d'ingrédients signifie plus d'inconnues.
Gabe Rainbow
17

https://github.com/reoxey/benchmark

référence

comparaison de vitesse de MySQL et MongoDB dans GOLANG1.6 et PHP5

système utilisé pour le benchmark: DELL cpu i5 4th gen 1.70Ghz * 4 ram 4GB GPU ram 2GB

Comparaison de vitesse de RDBMS vs NoSQL pour INSERT, SELECT, UPDATE, DELETE exécutant différents nombres de lignes 10,100,1000,10000,100000,1000000

Le langage utilisé pour exécuter est: PHP5 et le langage le plus rapide de 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
Reoxey
la source
myisam n'est pas innodb, aussi quelle version mongodb et moteur de stockage?
1
il est important de spécifier les versions de MySQL et MongoDB.
Miron
1
N'utilisez pas MyISAM. Utilisez des inserts en lots!
Rick James
MySQL est plus rapide que Mongodb dans la requête d'insertion?! cela ne semble pas vrai tant que mysql n'a pas besoin de préparer des colonnes et des relations. mysql select est plus rapide que mongodb select, mais dans l'insertion de requête, mongo est plus rapide
Exind
6

Voici une petite recherche qui a exploré RDBMS vs NoSQL en utilisant MySQL vs Mongo, les conclusions étaient conformes à la réponse de @Sean Reilly. En bref, l'avantage provient de la conception, pas d'une différence de vitesse brute. Conclusion à la page 35-36:

RDBMS vs NoSQL: comparaison des performances et de la mise à l'échelle

Le projet a testé, analysé et comparé les performances et l'évolutivité des deux types de bases de données. Les expériences réalisées comprenaient l'exécution de nombres et de types de requêtes différents, certains plus complexes que d'autres, afin d'analyser comment les bases de données évoluaient avec une charge accrue. Le facteur le plus important dans ce cas était le type de requête utilisé car MongoDB pouvait traiter plus rapidement les requêtes plus complexes, principalement en raison de son schéma plus simple au prix de la duplication des données, ce qui signifie qu'une base de données NoSQL peut contenir de grandes quantités de doublons de données. Bien qu'un schéma migré directement à partir du SGBDR puisse être utilisé, cela éliminerait l'avantage de la représentation sous-jacente des données des sous-documents par MongoDB qui permettait d'utiliser moins de requêtes vers la base de données lorsque les tables étaient combinées.Malgré le gain de performances que MongoDB avait sur MySQL dans ces requêtes complexes, lorsque le benchmark a modélisé la requête MySQL de manière similaire à la requête complexe MongoDB en utilisant des SELECT imbriqués, MySQL a obtenu les meilleurs résultats, bien qu'à des nombres de connexions plus élevés, les deux se soient comportés de manière similaire. Le dernier type de requête référencé qui était la requête complexe contenant deux JOINS et une sous-requête a montré l'avantage que MongoDB a sur MySQL en raison de son utilisation de sous-documents. Cet avantage se fait au détriment de la duplication des données qui entraîne une augmentation de la taille de la base de données. Si de telles requêtes sont typiques dans une application, il est important de considérer les bases de données NoSQL comme alternatives tout en tenant compte du coût de stockage et de la taille de la mémoire résultant de la plus grande taille de la base de données.

Jason Hitchings
la source
-6

Sur un seul serveur, MongoDb ne serait pas plus rapide que mysql MyISAM en lecture et en écriture, étant donné que les tailles de table / doc sont petites de 1 Go à 20 Go.
MonoDB sera plus rapide sur Parallel Reduce sur les clusters multi-nœuds, où Mysql ne peut PAS évoluer horizontalement.

zhuomin chen
la source
5
Pouvez-vous fournir des preuves ou plus de détails pour étayer cela?
Steve Westbrook
Impossible de mettre à l'échelle horizontalement? Et NDB? DRBD a soutenu MySQL?
Ernestas
Ce n'est pas vrai. MongoDB a une limite de documents de 16MD. Mysql peut avoir beaucoup plus si vous le souhaitez