MySQL vs MongoDB 1000 lê

321

Estou muito empolgado com o MongoDb e tenho testado recentemente. Eu tinha uma tabela chamada posts no MySQL com cerca de 20 milhões de registros indexados apenas em um campo chamado 'id'.

Eu queria comparar a velocidade com o MongoDB e fiz um teste que obteria e imprimiria 15 registros aleatoriamente em nossos enormes bancos de dados. Executei a consulta cerca de 1.000 vezes cada uma para mysql e MongoDB e estou surpreso por não notar muita diferença de velocidade. Talvez o MongoDB seja 1,1 vezes mais rápido. Isso é muito decepcionante. Existe algo que estou fazendo de errado? Eu sei que meus testes não são perfeitos, mas o MySQL é parecido com o MongoDb quando se trata de ler tarefas intensivas.


Nota:

  • Tenho dual core + (2 threads) i7 cpu e 4GB de RAM
  • Eu tenho 20 partições no MySQL cada um dos 1 milhão de registros

Código de exemplo usado para testar o 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 exemplo para testar o 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
fonte
11
Quais são os horários reais?
Abe Petrillo
30
Eu não sou um DBA, então este é um comentário, não uma resposta, mas a velocidade não deve ser a principal consideração ao escolher entre o MySQL e o MongoDB. Coisas como esquema versus esquema (ou seja, com que frequência seu esquema de dados precisa mudar) e escala de tamanho (ou seja, quão fácil é compartilhar seus dados para que uma leitura típica exija dados de apenas um servidor) é mais importante para uma escolha como isso.
Rossdavidh 14/03/12
17
Como pode ser mais rápido na leitura? Lê de um dispositivo mecânico. O mesmo que o MySQL. Depende da velocidade do dispositivo, não é possível empregar uma mágica estranha via código para romper os limites do hardware.
NB
7
Esta questão só me faz lembrar disto: mongodb-is-web-scale.com
oligofren
13
As pessoas estão enganadas ao sentir que iriam com uma ou outra. Você precisará de microondas e forno em sua cozinha. Você simplesmente não pode dizer que vou usar apenas um ou outro. Os casos de uso para ambos os sistemas são diferentes. Se você precisar de ACID para parte do seu aplicativo, use o RDBMS, se não se preocupa com a consistência e as restrições e suas entidades podem ser armazenadas como uma em uma (coleções), use o MongoDB. Você vai acabar usando um sistema híbrido, o ponto principal é decidir o que armazenar onde.
Teoman shipahi

Respostas:

647

O MongoDB não é magicamente mais rápido. Se você armazena os mesmos dados, organizados basicamente da mesma maneira e os acessa exatamente da mesma maneira, não deve esperar que seus resultados sejam totalmente diferentes. Afinal, MySQL e MongoDB são ambos GPL, portanto, se o Mongo tivesse algum código de IO magicamente melhor, a equipe do MySQL poderia incorporá-lo à sua base de código.

As pessoas estão vendo o desempenho do MongoDB no mundo real, em grande parte porque o MongoDB permite que você consulte de uma maneira diferente, mais sensível à sua carga de trabalho.

Por exemplo, considere um design que persistisse com muitas informações sobre uma entidade complicada de maneira normalizada. Isso poderia facilmente usar dezenas de tabelas no MySQL (ou qualquer banco de dados relacional) para armazenar os dados na forma normal, com muitos índices necessários para garantir a integridade relacional entre as tabelas.

Agora considere o mesmo design com um repositório de documentos. Se todas essas tabelas relacionadas estiverem subordinadas à tabela principal (e geralmente são), você poderá modelar os dados para que toda a entidade seja armazenada em um único documento. No MongoDB, você pode armazenar isso como um único documento, em uma única coleção. É aqui que o MongoDB começa a permitir um desempenho superior.

No MongoDB, para recuperar toda a entidade, você deve executar:

  • Uma pesquisa de índice na coleção (supondo que a entidade seja buscada pelo ID)
  • Recuperar o conteúdo de uma página do banco de dados (o documento json binário real)

Portanto, uma pesquisa em árvore b e uma página binária são lidas. Log (n) + 1 E / S. Se os índices puderem residir inteiramente na memória, 1 IO.

No MySQL com 20 tabelas, você deve executar:

  • Uma pesquisa de índice na tabela raiz (novamente, assumindo que a entidade seja buscada pelo ID)
  • Com um índice em cluster, podemos assumir que os valores para a linha raiz estão no índice
  • Mais de 20 pesquisas de intervalo (provavelmente em um índice) para o valor pk da entidade
  • Provavelmente, esses não são índices agrupados, portanto, as mesmas 20 ou mais pesquisas de dados quando descobrimos quais são as linhas filho apropriadas.

Portanto, o total para o mysql, mesmo assumindo que todos os índices estejam na memória (o que é mais difícil, pois há 20 vezes mais deles) é de cerca de 20 pesquisas de intervalo.

Essas pesquisas de intervalo provavelmente são compostas por E / S aleatórias - tabelas diferentes definitivamente residem em pontos diferentes no disco, e é possível que linhas diferentes no mesmo intervalo na mesma tabela para uma entidade possam não ser contíguas (dependendo de como a entidade foi atualizado etc.).

Portanto, neste exemplo, a contagem final é cerca de 20 vezes mais IO com MySQL por acesso lógico, em comparação com o MongoDB.

É assim que o MongoDB pode aumentar o desempenho em alguns casos de uso .

Sean Reilly
fonte
43
e se apenas colocarmos uma tabela principal no mysql?
Ariso1
99
@ariso: Isso é otimização por desnormalização. Pode fornecer um aumento de desempenho. No entanto, se você fizer isso, estará jogando fora seu design limpo e todo o poder (para não mencionar a maioria dos recursos) de um banco de dados relacional. E isso realmente funciona até você atingir o limite da coluna.
Sean Reilly
7
@SeanReilly Seu exemplo com entidades (deve ser editado com objetos, não há programação orientada a entidades :)) é inválido. Como o Ariso disse, você pode serializar um objeto e armazená-lo no banco de dados e desserializar quando necessário (qualquer forma de serialização). O verdadeiro poder dos objetos persistentes é mantido em sistemas oodbms e não documnet db. Mas eu concordo que cada um tem seu próprio objetivo e força (mas seu exemplo ofusca mais a visão e a relevância deste tópico).
Geo C.
9
20 junções, eu diria, provavelmente não é a melhor consulta sobre o melhor esquema de banco de dados que poderia ser.
Audrius Meskauskas
8
@SeanReilly, achei seu exemplo muito útil. Você pode criar uma interface especial para o MySQL que serialize e desserialize automaticamente objetos em tabelas e se comporte da maneira que o mongodb faz. Mas então, por que não usar apenas algo especificamente projetado para ser usado dessa maneira? Também o seu uso de "entidade" faz sentido. O ponto é que você está organizando os dados como documentos e não como campos em uma tabela. Se o documento é ou não um objeto composto em uma linguagem OO é irrelevante para o exemplo.
BHS
57

Você tem simultaneidade, ou seja, usuários simultâneos? Se você executar 1000 vezes a consulta diretamente, com apenas um encadeamento, quase não haverá diferença. Muito fácil para esses mecanismos :)

Mas sugiro fortemente que você crie uma sessão de teste de carga real, o que significa usar um injetor como o JMeter com 10, 20 ou 50 usuários AO MESMO TEMPO para que você possa realmente ver a diferença (tente incorporar esse código dentro de uma página da Web JMeter poderia consultar).

Eu fiz isso hoje em um único servidor (e uma coleção / tabela simples) e os resultados são bastante interessantes e surpreendentes (o MongoDb foi realmente mais rápido em gravações e leituras, comparado ao mecanismo MyISAM e ao mecanismo InnoDb).

Isso realmente deve fazer parte do seu teste: mecanismo de concorrência e MySQL. Então, as necessidades de aplicativos e design de dados / esquema são, obviamente, enormes requisitos, além do tempo de resposta. Deixe-me saber quando você obtiver resultados, também estou precisando de informações sobre isso!

theAndroid
fonte
42
Você pode compartilhar seus resultados?
Imran Omar Bukhsh
1
Ya, os resultados serão muito úteis
Vasil Popov
3
Certamente isso seria apenas escalável ... se fosse Maçãs para Maçãs, como eles disseram no restante deste tópico. Portanto, se no avg executa x, agora simula a partir de várias fontes, explique por que o mongo seria mais rápido. ou seja, digamos apenas por uma questão de acordo que o mysql estava no avg mais rápido para uma única solicitação ... por que o mongo agora se tornaria mais rápido para várias? Eu não acho isso muito científico. Estou dizendo que o teste é válido ... mas não tenho tanta certeza de como a diferença seria enorme se você comparasse maçãs com maçãs, como o restante do tópico explica.
Seabizkit
35

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

10 linhas

mysql insert: 1702ms
mysql select: 11ms

mongo insert: 47ms
mongo select: 12ms

100 linhas

mysql insert: 8171ms
mysql select: 10ms

mongo insert: 167ms
mongo select: 60ms

1000 linhas

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

mongo insert: 1013ms
mongo select: 677ms

10.000 linhas

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

mongo insert: 9956ms (9.95 seconds)
mongo select: 4539ms (4.539 seconds)
user2081518
fonte
91
15 min para inserir 10.000 linhas? Esse é um banco de dados MySQL muito anêmico. Na minha experiência, se uma operação desse tipo atingir 1s de duração, meu telefone acenderá com reclamações. :)
Mordechai
1
Xtreme Biker dê uma olhada no link. Postei o teste de outras pessoas com outras configurações.
user2081518
14
Alguns pontos: 1) O Mysql precisa ser otimizado e configurado corretamente, existem muitas maneiras diferentes de inserir grandes quantidades de dados e, feito corretamente, pode levar 0,1% dos 15min, veja esta página por exemplo. 2) O MongoDB não grava os dados no disco imediatamente, e é por isso que "parece" mais rápido, mas se o seu computador travar, os dados serão perdidos. 3) A leitura é muito mais rápida no MySQL
elipoultorak 27/11/2015
81
15min para 10.000 linhas? Você digitou cada linha? =))))
Iurie Manea
7
qualquer um que acredita que uma reivindicação que leva 1,7 segundos para inserir linhas dez em mysql merece a dor que começa a partir mongo
John Haugeland
20

man ,,, a resposta é que você está basicamente testando PHP e não um banco de dados.

não se incomode em repetir os resultados, comentando a impressão ou não. há um pedaço de tempo.

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

enquanto o outro pedaço gasta gerando vários números aleatórios.

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

    }
    return $numbers;
}

então há uma grande diferença b / w implodir e dentro

e finalmente o que está acontecendo aqui. parece criar uma conexão a cada vez, assim testando o tempo de conexão mais o tempo de consulta.

$m = new Mongo();

vs

$db = new AQLDatabase();

portanto, seu 101% mais rápido pode ser 1000% mais rápido para a consulta subjacente sem jazz.

urghhh.

Gabe Rainbow
fonte
4
naturalmente, a prática de codificação pode fazer uma grande diferença em qualquer situação, mas isso não é específico para nenhum tipo de idioma, API ou extensão. a geração de números aleatórios antes de iniciar o timer fará diferença, mas a maior parte do tempo no processo é sem dúvida das transações do banco de dados. a geração de números aleatórios é trivial, os bancos de dados SQL e NoSQL não.
JSON
1
não escolha o número da rand. claramente você perdeu a conexão de criação de cada vez. todos os problemas se somam ao teste de algo diferente do pretendido.
Gabe Rainbow
2
Não, não perdeu. O MySQL não fechará a conexão até que o script termine, a menos que mysqli_close () seja chamado. Caso contrário, as chamadas repetidas para mysqli_connect () puxarão apenas o recurso mysql existente da tabela de recursos atual, em vez de se comprometerem com um novo procedimento de conexão. Não sei exatamente qual é o objeto AQLDatabase, mas se ele usar a lib do mysql (o que provavelmente faz), ele terá o mesmo comportamento. A extensão MongoDB usa o pool de conexões, portanto, a mesma coisa básica ocorre ao criar uma 'conexão' do mongodb mais de uma vez em um script.
JSON
Concordo que seu benchmark poderia ter sido feito de maneira diferente, mas reflete os mesmos resultados básicos que outros bancos MySQL vs Mongo que eu já vi. O Mongo é tipicamente mais rápido ao inserir (muito mais rápido para inserções mais simples) e o MySQL é tipicamente mais rápido ao selecionar.
JSON
reconhecidamente, eu era muito intratável; foi essa seqüência html concat de "<br>" que realmente 'me levou' a sair. você não precisa de uma boa impressão nos testes. mesmo iterando, parece um teste de php e não um teste de banco de dados. No geral, esse momento 'possivelmente / talvez' do AQLDatabase ... mais ingredientes significa mais incógnitas.
Gabe Rainbow
17

https://github.com/reoxey/benchmark

referência

comparação de velocidade do MySQL e MongoDB em GOLANG1.6 e PHP5

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

Comparação de velocidade de RDBMS vs NoSQL para INSERT, SELECT, UPDATE, DELETE executando um número diferente de linhas 10,100,1000,10000,100000,1000000

O idioma usado para executar é: PHP5 e o idioma mais rápido do 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
fonte
myisam não é innodb, também qual versão do mongodb e mecanismo de armazenamento?
1
é importante especificar as versões MySQL e MongoDB.
Miron
1
Não use o MyISAM. Use inserções em lote!
Rick James
O MySQL é mais rápido que o Mongodb na consulta Insert ?! parece não ser verdade até que o mysql precise preparar colunas e re-relações. o mysql select é mais rápido que o mongodb select, mas na consulta de inserção, o mongo é mais rápido
Exind
6

Aqui está uma pequena pesquisa que explorou RDBMS vs NoSQL usando MySQL vs Mongo, as conclusões foram alinhadas com a resposta de @Sean Reilly. Em resumo, o benefício vem do design, e não de uma diferença bruta de velocidade. Conclusão nas páginas 35-36:

RDBMS vs NoSQL: comparação de desempenho e dimensionamento

O projeto testou, analisou e comparou o desempenho e a escalabilidade dos dois tipos de banco de dados. Os experimentos realizados incluíram a execução de diferentes números e tipos de consultas, algumas mais complexas do que outras, para analisar como os bancos de dados eram escalados com maior carga. O fator mais importante nesse caso foi o tipo de consulta usado, pois o MongoDB poderia lidar com consultas mais complexas mais rapidamente devido principalmente ao seu esquema mais simples no sacrifício da duplicação de dados, o que significa que um banco de dados NoSQL pode conter grandes quantidades de duplicatas de dados. Embora um esquema migrado diretamente do RDBMS possa ser usado, isso eliminaria a vantagem da representação de dados subjacentes do MongoDB de subdocumentos, o que permitia o uso de menos consultas no banco de dados à medida que as tabelas eram combinadas.Apesar do ganho de desempenho que o MongoDB teve sobre o MySQL nessas consultas complexas, quando o benchmark modelou a consulta MySQL de maneira semelhante à consulta complexa MongoDB usando SELECTs aninhados, o MySQL teve melhor desempenho, embora em um número maior de conexões, os dois se comportassem da mesma maneira. O último tipo de consulta comparada, que era a consulta complexa contendo duas JOINS e uma subconsulta, mostrou a vantagem que o MongoDB tem sobre o MySQL devido ao uso de subdocumentos. Essa vantagem tem o custo da duplicação de dados, o que causa um aumento no tamanho do banco de dados. Se essas consultas são típicas em um aplicativo, é importante considerar os bancos de dados NoSQL como alternativas, levando em consideração o custo em armazenamento e tamanho da memória resultante do tamanho maior do banco de dados.

Jason Hitchings
fonte
-6

No servidor único, o MongoDb não seria mais rápido que o mysql MyISAM em leitura e gravação, dado que os tamanhos de tabela / documento são pequenos de 1 GB a 20 GB.
O MonoDB será mais rápido no Parallel Reduce em clusters de vários nós, onde o Mysql NÃO pode ser dimensionado horizontalmente.

zhuomin chen
fonte
5
Você pode fornecer alguma evidência ou mais detalhes para respaldar isso?
Steve Westbrook
Não é possível dimensionar horizontalmente? E o NDB? MySQL suportado por DRBD?
Ernestas
Isso não é verdade. O MongoDB possui um limite de documentos de 16MD. Mysql pode ter muito mais se você gosta