MySQL vs MongoDB 1000 lecturas

321

He estado muy entusiasmado con MongoDb y lo he estado probando últimamente. Tenía una tabla llamada posts en MySQL con aproximadamente 20 millones de registros indexados solo en un campo llamado 'id'.

Quería comparar la velocidad con MongoDB y ejecuté una prueba que obtendría e imprimiría 15 registros al azar de nuestras enormes bases de datos. Ejecuté la consulta unas 1,000 veces cada una para mysql y MongoDB y me sorprende que no note mucha diferencia en la velocidad. Quizás MongoDB es 1.1 veces más rápido. Eso es muy decepcionante. ¿Hay algo que estoy haciendo mal? Sé que mis pruebas no son perfectas, pero MySQL está a la par con MongoDb cuando se trata de leer tareas intensivas.


Nota:

  • Tengo dual core + (2 hilos) i7 cpu y 4GB ram
  • Tengo 20 particiones en MySQL, cada una de 1 millón de registros

Código de muestra utilizado para probar 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;
}

?>


Código de muestra para probar 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
fuente
11
¿Cuáles son los tiempos reales?
Abe Petrillo
30
No soy un DBA, así que este es un comentario, no una respuesta, pero la velocidad no debería ser la consideración principal al elegir entre MySQL y MongoDB. Cosas como sin esquema versus esquema (es decir, con qué frecuencia debe cambiar su esquema de datos) y el tamaño de escala (es decir, qué tan fácil es fragmentar sus datos para que una lectura típica requiera datos de un solo servidor) son más importantes para elegir Me gusta esto.
rossdavidh
17
¿Cómo puede ser más rápido en la lectura? Se lee desde un dispositivo mecánico. Igual que MySQL. Depende de la velocidad del dispositivo en sí, no puede emplear un poco de magia extraña a través del código para romper los límites del hardware.
NB
77
Esta pregunta solo me recuerda esto: mongodb-is-web-scale.com
oligofren
13
Las personas se equivocan al sentir que irían con uno u otro. Necesitará microondas y horno en su cocina. Simplemente no puedes decir que solo usaré uno u otro. Los casos de uso para ambos sistemas son diferentes. Si necesita ACID para parte de su aplicación, use RDBMS, si no le importa la consistencia y las restricciones y sus entidades se pueden almacenar como todas en una (colecciones), use MongoDB. Terminará utilizando un sistema híbrido, el punto clave es decidir qué almacenar dónde.
Teoman shipahi

Respuestas:

647

MongoDB no es mágicamente más rápido. Si almacena los mismos datos, organizados básicamente de la misma manera, y accede a ellos exactamente de la misma manera, entonces no debería esperar que sus resultados sean muy diferentes. Después de todo, MySQL y MongoDB son GPL, por lo que si Mongo tuviera un código IO mágicamente mejor, entonces el equipo de MySQL podría incorporarlo a su base de código.

La gente está viendo el rendimiento de MongoDB en el mundo real en gran medida porque MongoDB le permite realizar consultas de una manera diferente que sea más sensible a su carga de trabajo.

Por ejemplo, considere un diseño que persistió con mucha información sobre una entidad complicada de manera normalizada. Esto podría usar fácilmente docenas de tablas en MySQL (o cualquier base de datos relacional) para almacenar los datos en forma normal, con muchos índices necesarios para garantizar la integridad relacional entre las tablas.

Ahora considere el mismo diseño con una tienda de documentos. Si todas esas tablas relacionadas están subordinadas a la tabla principal (y a menudo lo están), es posible que pueda modelar los datos de modo que toda la entidad se almacene en un solo documento. En MongoDB puede almacenar esto como un solo documento, en una sola colección. Aquí es donde MongoDB comienza a permitir un rendimiento superior.

En MongoDB, para recuperar toda la entidad, debe realizar:

  • Una búsqueda de índice en la colección (suponiendo que la entidad es obtenida por id)
  • Recupere el contenido de una página de base de datos (el documento json binario real)

Entonces, una búsqueda de árbol b y una página binaria leída. Log (n) + 1 IOs. Si los índices pueden residir completamente en la memoria, entonces 1 IO.

En MySQL con 20 tablas, debe realizar:

  • Una búsqueda de índice en la tabla raíz (de nuevo, suponiendo que la entidad se recupere por id)
  • Con un índice agrupado, podemos suponer que los valores para la fila raíz están en el índice
  • Más de 20 búsquedas de rango (con suerte en un índice) para el valor pk de la entidad
  • Probablemente estos no sean índices agrupados, por lo que las mismas más de 20 búsquedas de datos una vez que descubramos cuáles son las filas secundarias apropiadas.

Entonces, el total de mysql, incluso suponiendo que todos los índices estén en la memoria (lo cual es más difícil ya que hay 20 veces más de ellos) es de aproximadamente 20 búsquedas de rango.

Es probable que estas búsquedas de rango estén compuestas de E / S aleatorias: diferentes tablas definitivamente residirán en diferentes puntos en el disco, y es posible que diferentes filas en el mismo rango en la misma tabla para una entidad no sean contiguas (dependiendo de cómo haya sido la entidad) actualizado, etc.).

Entonces, para este ejemplo, la cuenta final es aproximadamente 20 veces más IO con MySQL por acceso lógico, en comparación con MongoDB.

Así es como MongoDB puede aumentar el rendimiento en algunos casos de uso .

Sean Reilly
fuente
43
¿Qué pasa si solo ponemos una tabla principal en mysql?
ariso
99
@ariso: Esta es la optimización por denormalización. Puede proporcionar un aumento de rendimiento. Sin embargo, si haces esto, entonces estás desperdiciando tu diseño limpio y toda la potencia (sin mencionar la mayoría de las características) de una base de datos relacional. Y solo funciona realmente hasta llegar al límite de la columna.
Sean Reilly
77
@SeanReilly Su ejemplo con entidades (debe editarse con objetos, no hay programación orientada a entidades :)) no es válido. Como dijo ariso, puede serializar un objeto y almacenarlo en la base de datos y deserializarlo cuando sea necesario (cualquier forma de serialización). El verdadero poder de los objetos persistentes se mantiene en sistemas oodbms no documnet db. Pero estoy de acuerdo en que cada uno tiene su propio propósito y fuerza (pero su ejemplo ofusca más la visión y relevancia de este tema).
Geo C.
99
20 combinaciones, diría, probablemente no sea la mejor consulta sobre el mejor esquema de base de datos que podrían ser.
Audrius Meskauskas
8
@SeanReilly Encontré su ejemplo muy útil. Podría crear una interfaz especial para MySQL que serializa y deserializa automáticamente los objetos en tablas y se comporta de la manera que lo hace mongodb. Pero entonces, ¿por qué no usar algo específicamente diseñado para usarse de esa manera? También su uso de "entidad" tiene sentido. El punto es que está organizando los datos como documentos en lugar de como campos en una tabla. Si el documento es o no un objeto compuesto en un lenguaje OO es irrelevante para el ejemplo.
BHS
57

¿Tiene concurrencia, es decir, usuarios simultáneos? Si solo ejecuta 1000 veces la consulta directamente, con solo un hilo, casi no habrá diferencia. Demasiado fácil para estos motores :)

PERO le sugiero que cree una verdadera sesión de prueba de carga, lo que significa usar un inyector como JMeter con 10, 20 o 50 usuarios AL MISMO TIEMPO para que realmente pueda ver la diferencia (intente incrustar este código dentro de una página web JMeter podría consultar).

Lo hice hoy en un solo servidor (y una simple colección / tabla) y los resultados son bastante interesantes y sorprendentes (MongoDb fue realmente más rápido en escrituras y lecturas, en comparación con el motor MyISAM y el motor InnoDb).

Esto realmente debería ser parte de su prueba: concurrencia y motor MySQL. Entonces, las necesidades de diseño y aplicación de datos / esquemas son, por supuesto, requisitos enormes, más allá de los tiempos de respuesta. Avísame cuando obtengas resultados, ¡también necesito comentarios sobre esto!

el androide
fuente
42
¿Puedes compartir tus resultados?
Imran Omar Bukhsh
1
Sí, los resultados serán muy útiles
Vasil Popov
3
Seguramente esto, esto simplemente se escalaría ... si se tratara de Manzanas a Manzanas como han estado diciendo en el resto de este tema. Entonces, si en promedio realiza x, ahora simula desde múltiples fuentes, explique por qué mongo sería más rápido. es decir, solo por acuerdo, mysql estaba en promedio más rápido para una sola solicitud ... ¿por qué mongo ahora se volvería más rápido para múltiples? No creo que esto sea muy científico. Estoy diciendo que la prueba es válida ... pero no estoy tan seguro de cómo la diferencia sería enorme si estuvieras comparando manzanas con manzanas como explica el resto del tema.
Seabizkit
35

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

10 filas

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms

100 filas

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms

1000 filas

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

mongo insert: 1013ms
mongo select: 677ms

10.000 filas

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

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)
usuario2081518
fuente
9191
15 min para insertar 10.000 filas? Esa es una base de datos MySQL muy anémica. En mi experiencia, si tal operación se aproxima a 1s de duración, mi teléfono se ilumina con quejas. :)
Mordechai
1
Xtreme Biker mira el enlace. Publiqué la prueba de otras personas con otras configuraciones.
user2081518
14
Algunos puntos: 1) Mysql necesita ser optimizado y configurado correctamente, hay muchas maneras diferentes de insertar grandes cantidades de datos, y si se hace correctamente puede tomar el 0.1% de los 15 minutos, vea esta página por ejemplo. 2) MongoDB no escribe los datos en el disco de inmediato, por lo que "se ve" más rápido, pero si su computadora falla, los datos se pierden. 3) La lectura es mucho más rápida en MySQL
elipoultorak
81
15min para 10.000 filas? ¿Escribiste cada fila? =))))
Iurie Manea
77
cualquiera que crea una demanda que se tarda 1,7 segundos para insertar filas en MySQL diez merece la pena que obtienen de mongo
John Haugeland
20

hombre ,,, la respuesta es que básicamente estás probando PHP y no una base de datos.

no se moleste en repetir los resultados, ya sea comentando la impresión o no. Hay un poco de tiempo.

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

mientras que la otra parte es gastar un montón de números rand.

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

    }
    return $numbers;
}

entonces hay una gran diferencia b / w implode y en.

y finalmente lo que está pasando aquí. parece crear una conexión cada vez, por lo tanto, prueba el tiempo de conexión más el tiempo de consulta.

$m = new Mongo();

vs

$db = new AQLDatabase();

por lo que su 101% más rápido podría ser 1000% más rápido para la consulta subyacente despojada de jazz.

urghhh

Gabe Rainbow
fuente
44
naturalmente, la práctica de codificación puede hacer una gran diferencia en cualquier situación, pero esto no es específico para ningún tipo de lenguaje, API o extensión. generar los números aleatorios antes de iniciar el temporizador marcará la diferencia, pero la mayoría del tiempo dentro del proceso es sin duda de las transacciones de la base de datos. la generación de números aleatorios es trivial, las bases de datos SQL y NoSQL no lo son.
JSON
1
no escoja el número de rand. claramente te perdiste la conexión de creación cada vez. todos los problemas se suman a probar algo diferente a lo previsto.
Gabe Rainbow
2
No, no te lo perdiste. MySQL no cerrará la conexión hasta que finalice el script a menos que se invoque mysqli_close (). De lo contrario, las llamadas repetidas a mysqli_connect () solo extraerán el recurso mysql existente de la tabla de recursos actual, en lugar de comprometerse con un nuevo procedimiento de conexión. No estoy exactamente seguro de cuál es el objeto AQLDatabase, pero si usa la biblioteca mysql (que probablemente lo haga) tendrá el mismo comportamiento. La extensión MongoDB usa la agrupación de conexiones, por lo que ocurre lo mismo al crear una 'conexión' mongodb más de una vez en un script.
JSON
Estoy de acuerdo en que su punto de referencia podría haberse hecho de manera diferente, pero refleja los mismos resultados básicos que otros bancos MySQL vs Mongo que he visto. Mongo suele ser más rápido al insertar (mucho más rápido para inserciones más simples) y MySQL suele ser más rápido al seleccionar.
JSON
Es cierto que era demasiado maleducado; fue esa cadena de html concat de "<br>" lo que realmente me 'urgió'. No necesita bonita impresión en las pruebas. incluso iterar parece una prueba de php y no una prueba de base de datos. en general, ese momento 'posiblemente / quizás' de AQLDatabase ... más ingredientes significa más incógnitas.
Gabe Rainbow
17

https://github.com/reoxey/benchmark

punto de referencia

Comparación de velocidad de MySQL y MongoDB en GOLANG1.6 y PHP5

sistema utilizado para benchmark: DELL cpu i5 4th gen 1.70Ghz * 4 ram 4GB GPU ram 2GB

Comparación de velocidad de RDBMS vs NoSQL para INSERTAR, SELECCIONAR, ACTUALIZAR, BORRAR ejecutando diferentes números de filas 10,100,1000,10000,100000,1000000

El lenguaje utilizado para ejecutar es: PHP5 y el lenguaje más rápido 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
fuente
myisam no es innodb, ¿también qué versión de mongodb y motor de almacenamiento?
1
Es importante especificar las versiones de MySQL y MongoDB.
Miron
1
No uses MyISAM. ¡Use insertos en lotes!
Rick James
¿MySQL es más rápido que Mongodb en Insertar consulta? no parece ser cierto hasta que mysql necesite preparar columnas y relaciones. mysql select es más rápido que mongodb select, pero en la consulta de inserción, mongo es más rápido
Exind
6

Aquí hay una pequeña investigación que exploró RDBMS vs NoSQL usando MySQL vs Mongo, las conclusiones estaban en línea con la respuesta de @Sean Reilly. En resumen, el beneficio proviene del diseño, no de una diferencia de velocidad en bruto. Conclusión en la página 35-36:

RDBMS vs NoSQL: Comparación de rendimiento y escala

El proyecto probó, analizó y comparó el rendimiento y la escalabilidad de los dos tipos de bases de datos. Los experimentos realizados incluyeron la ejecución de diferentes números y tipos de consultas, algunas más complejas que otras, con el fin de analizar cómo las bases de datos se escalaron con una mayor carga. El factor más importante en este caso fue el tipo de consulta utilizado, ya que MongoDB podría manejar consultas más complejas más rápido debido principalmente a su esquema más simple en el sacrificio de la duplicación de datos, lo que significa que una base de datos NoSQL puede contener grandes cantidades de duplicados de datos. Aunque podría utilizarse un esquema directamente migrado desde el RDBMS, esto eliminaría la ventaja de la representación de subdocumentos de datos subyacentes de MongoDB que permitió el uso de menos consultas hacia la base de datos a medida que se combinaban las tablas.A pesar de la ganancia de rendimiento que MongoDB tuvo sobre MySQL en estas consultas complejas, cuando el punto de referencia modeló la consulta MySQL de manera similar a la consulta compleja MongoDB utilizando SELECT anidados MySQL funcionó mejor aunque a un mayor número de conexiones los dos se comportaron de manera similar. El último tipo de consulta comparada, que era la consulta compleja que contenía dos JOINS y una subconsulta, mostró la ventaja que MongoDB tiene sobre MySQL debido a su uso de subdocumentos. Esta ventaja tiene el costo de la duplicación de datos, lo que provoca un aumento en el tamaño de la base de datos. Si tales consultas son típicas en una aplicación, entonces es importante considerar las bases de datos NoSQL como alternativas teniendo en cuenta el costo en almacenamiento y el tamaño de la memoria resultante del mayor tamaño de la base de datos.

Jason Hitchings
fuente
-6

En Single Server, MongoDb no sería más rápido que mysql MyISAM tanto en lectura como en escritura, dado que los tamaños de tabla / documento son pequeños de 1 GB a 20 GB.
MonoDB será más rápido en Parallel Reduce en clústeres de múltiples nodos, donde Mysql NO puede escalar horizontalmente.

zhuomin chen
fuente
55
¿Puede proporcionar alguna evidencia o más detalles para respaldar eso?
Steve Westbrook
No se puede escalar horizontalmente? ¿Qué hay de NDB? DRBD MySQL respaldado?
Ernestas
Esto no es verdad. MongoDB tiene un límite de documentos de 16MD. Mysql puede tener mucho más si lo desea