Benchmarking MongoDB do 3.6 ao 8.0 - Parte 1

  • Introdução

Este é um post em duas partes no qual compartilharei meus resultados pessoais após realizar uma série de testes de benchmarking do MongoDB 3.6 ao 8.0.

A ideia de dividir os artigos em partes diferentes foi para tornar a leitura mais dinâmica. Nesta primeira parte, explicarei mais sobre os motivos e como o processo foi feito, enquanto a Parte 2 se concentrará nos resultados em si.

Se você quiser pular para a Parte 2, pode clicar no link abaixo. Caso contrário, pode acompanhar esta primeira parte para mais detalhes tais quais o objetivo, ambiente de teste e como o benchmark foi realizado.

  • Objetivo

O objetivo e a motivação são bem simples, eu diria:

Entender se o desempenho do MongoDB mudou ao longo dos anos(versões).

Isso porque essa dúvida acontece a cada novo grande lançamento; Clientes/Usuários no geral sempre expressam preocupações sobre uma possível regressão de desempenho ao migrar para uma versão mais recente.

Embora não seja muito claro e organizado o modo como essa informação é apresentada, temos outros usuários realizando benchmarks e relatando problemas relacionados à perda de desempenho ao longo das versões:

Dito isso, este teste de benchmark visa entender essas preocupações, avaliando o desempenho de diferentes versões do MongoDB em um ambiente controlado e único.

Embora este teste não pretenda ser a palavra final sobre o desempenho do MongoDB, ele visa servir como um esforço para organizar e elucidar essa questão em todas as versões testadas.

  • Ambiente de Teste

Servidor de banco de dados com o seguinte perfil de configuração:

  • CPU: AMD Ryzen(TM) 7 5800X — 8C/16T
  • RAM: 16 GB DDR4 a 3200 MHz (2 x 8 GB).
  • Discos: 512GB(SSD) -> Instalação do SO e do Banco de Dados. | 512GB(NVMe) -> dbpath do MongoDB.
  • SO: Oracle Linux 8.10.
  • Kernel: 4.18.0–553.el8_10.x86_64

Para o servidor cliente, temos o seguinte perfil de configuração:

  • CPU: Intel(R) Core(TM) i7–9750H CPU
  • RAM: 32 GB DDR4 a 2666 MHz (2 x 16 GB).
  • SO: Oracle Linux 8.10.
  • Kernel: 4.18.0–553.el8_10.x86_64
  • Topologia

Replica Set de nó único.

Esta topologia foi escolhida porque o foco não está na latência de replicação, controle de fluxo (flow control), consultas scatter-gather, leituras em secundários, ou quaisquer outras funcionalidades que pudessem influenciar o desempenho bruto. Em vez disso, o objetivo é avaliar como o desempenho do MongoDB mudou entre as diferentes versões sem a influência de possíveis features.

  • Configuração

Do lado do SO para o banco de dados, todas as notas de produção e melhores práticas foram aplicadas adequadamente:

Do lado do Banco de Dados, a instância está rodando com parâmetros padrão, com apenas Replica Set e Authorization (autorização) habilitados:

  • Ferramenta de Benchmarking

A ferramenta utilizada para este teste foi o mongo-perf.

  • Versão do Driver — PyMongo 4.4.0.
  • Versão do Python — Python3.8.

Conforme a documentação de compatibilidade, PyMongo 4.4.0 e Python3.8 fornecem toda a compatibilidade necessária do 3.6 ao 8.0.

A ferramenta mongo-perf utiliza scripts Python para conduzir execuções de testes específicos que avaliam vários aspectos de desempenho. Atualmente, cerca de 34 scripts estão disponíveis para uso, mas eu não usei todos eles.

Para os testes, os seguintes scripts foram selecionados:

A escolha desses scripts selecionados se deve ao fato de que eles podem testar de forma abrangente operações de CRUD, na qual maior parte dos ambientes recebem.

Os scripts simple_insert.js, simple_update.js, simple_query.js e simple_remove.js cobrem o básico de criação, modificação, recuperação e exclusão de documentos. O complex_update.js adiciona complexidade ao envolver operações avançadas e múltiplos índices. O complex_insert.js e o partial_index.js avaliam o desempenho em cenários mais exigentes, como inserções sequenciais e aleatórias, com e sem contenção, envolvendo valores grandes e índices multi-key.

  • Metodologia e Consideração Final

Este teste foi conduzido na época do lançamento do MongoDB 8.0, e os últimos patch releases disponíveis das outras versões foram usados, de acordo:

  • 3.6.23 -> 4.0.28  -> 4.2.25 -> 4.4.29 -> 5.0.29  -> 6.0.18 -> 7.0.14  -> 8.0.0.

O Red Hat 8 foi escolhido como sistema exclusivamente devido à sua alta compatibilidade entre as versões testadas. Mais adiante nesta seção, eu detalho melhor os testes, mas abaixo, temos um diagrama mostrando como as versões do MongoDB foram testadas.

  • Cada versão foi testada seguindo a abordagem de upgrade de patch:
Tudo começou com o 3.6.23.

Abaixo, mais detalhes de como o processo de benchmark ocorreu:

É um shell script que interage com os testcases da ferramenta mongo-perf como listado anteriormente; Da ferramenta de benchmark, vale a pena mencionar as opções utilizadas:

-t $th:

  • Define o número de threads a serem usadas no benchmark.
  • A variável $th é substituída dinamicamente por valores no loop (ex: 1, 2, 4, 8, 16).

-trialTime 1:

  • Define a duração de cada tentativa em segundos; No teste, cada tentativa dura 1 segundo.

-writeCmd true:

  • Habilita o uso de write commands (comandos de escrita) (ex: insert, update, delete) em vez de operações de escrita legadas.
  • O MongoDB introduziu os write commands em versões mais recentes para operações de escrita mais eficientes.

-readCmd true:

  • Habilita o uso de read commands (comandos de leitura) (ex: find, getMore) em vez de operações de leitura legadas.

-w 1:

  • Especifica o nível de write concern.

Com relação o script, cada teste de CRUD foi executado dez vezes para o número de threads fornecido (1, 2, 4, 8, 16) pela duração de um segundo.

  • Por exemplo: O simple_insert.js é um script que testa diferentes operações de inserção, cada uma dessas operações foi executada por 1 segundo, 10 vezes usando 1 thread. Após terminar essa sequência de operações, o loop reinicia, mas desta vez as operações para o simple_insert.js serão testadas com 2 threads, depois 4 e assim por diante até esgotar a variável de threads.

Após executar todos os scripts CRUD mencionados para uma versão, uma limpeza de dados foi realizada. Para cada operação testada, teremos 10 saídas distintas. Os outliers (o mais rápido e o mais lento) foram removidos, e as outras 8 operações restantes são somadas e divididas, gerando uma média de valores para aquela operação.

  • Por exemplo: O simple_insert.js tem a operação Insert.EmptyCapped, que basicamente testa a inserção de um documento vazio em uma capped collection. Temos então 10 tempos de execução distintos rodando com 1 thread: 547.96, 552.54, 561.64, 562.18, 562.73, 564.83, 567.14, 570.20, 542.68, 567.62. Os outliers seriam o número mais alto = 570.20 e o número mais baixo = 542.68; A média de operações por segundo seria 560,83.

Este cálculo foi aplicado a todas as operações para todas as threads e foi organizado em tabelas, que você pode ver e seguir na parte 2, onde temos o relatório finalizado.

Até mais!

Leave a Comment

Comments

No comments yet. Why don’t you start the discussion?

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *