Como Monitorar o Desempenho do MongoDB

O autor selecionou o Fundo de Internet Aberta/Liberdade de Expressão para receber uma doação como parte do programa Escreva para Doações.

Introdução

O monitoramento é uma parte fundamental da administração de banco de dados, pois permite entender o desempenho e a saúde geral do seu banco de dados. Ao monitorar o desempenho do seu banco de dados, você pode ter uma melhor noção da sua capacidade atual, observar como a carga de trabalho muda ao longo do tempo e planejar antecipadamente para dimensionar o banco de dados assim que ele começar a se aproximar de seus limites. Também pode ajudar a detectar problemas de hardware subjacentes ou comportamentos anormais, como um pico inesperado no uso do banco de dados. Por último, o monitoramento pode ajudar a diagnosticar problemas com aplicativos que usam o banco de dados, como consultas de aplicativos que causam gargalos.

O MongoDB já vem instalado com uma variedade de ferramentas e utilitários que você pode usar para observar o desempenho do seu banco de dados. Neste tutorial, você aprenderá como monitorar métricas de banco de dados sob demanda usando comandos e ferramentas integradas. Você também se familiarizará com o perfilador de banco de dados do MongoDB, que pode ajudá-lo a detectar consultas mal otimizadas.

Pré-requisitos

Para seguir este tutorial, você precisará:

  • A server with a regular, non-root user with sudo privileges and a firewall configured with UFW. This tutorial was validated using a server running Ubuntu 20.04, and you can prepare your server by following this initial server setup tutorial for Ubuntu 20.04.
  • O MongoDB instalado no seu servidor. Para configurar isso, siga nosso tutorial sobre Como Instalar o MongoDB no Ubuntu 20.04.
  • A instância do MongoDB do seu servidor deve estar segura, habilitando a autenticação e criando um usuário administrativo. Para proteger o MongoDB dessa forma, siga nosso tutorial sobre Como Proteger o MongoDB no Ubuntu 20.04.
  • Familiaridade com a consulta de coleções do MongoDB e filtragem de resultados. Para aprender como usar consultas do MongoDB, siga nosso guia sobre Como Criar Consultas no MongoDB.

Nota: Os tutoriais vinculados sobre como configurar seu servidor, instalar o MongoDB e proteger a instalação do MongoDB referem-se ao Ubuntu 20.04. Este tutorial se concentra no MongoDB em si, não no sistema operacional subjacente. Em geral, funcionará com qualquer instalação do MongoDB, independentemente do sistema operacional, desde que a autenticação tenha sido habilitada.

Passo 1 — Preparando os Dados de Teste

Para explicar como você pode monitorar o desempenho do MongoDB, esta etapa descreve como abrir o shell do MongoDB para se conectar à instância do MongoDB instalada localmente e criar uma coleção de amostra dentro dela.

Para criar a coleção de amostra usada neste guia, conecte-se ao shell do MongoDB como seu usuário administrativo. Este tutorial segue as convenções do tutorial de segurança do MongoDB como pré-requisito e assume que o nome deste usuário administrativo é AdminSammy e seu banco de dados de autenticação é admin. Certifique-se de alterar esses detalhes no comando a seguir para refletir sua própria configuração, se for diferente:

  1. mongo -u AdminSammy -p --authenticationDatabase admin

Insira a senha definida durante a instalação para acessar o shell. Após fornecer a senha, você verá o sinal de prompt >.

Nota: Em uma conexão nova, o shell do MongoDB se conectará ao banco de dados test por padrão. Você pode usar com segurança este banco de dados para experimentar o MongoDB e o shell do MongoDB.

Alternativamente, você pode mudar para outro banco de dados para executar todos os comandos de exemplo dados neste tutorial. Para mudar para outro banco de dados, execute o comando use seguido pelo nome do seu banco de dados:

  1. use database_name

O monitoramento do banco de dados não é muito prático ou útil ao trabalhar com um pequeno conjunto de dados, já que o sistema de banco de dados só precisará escanear alguns registros para qualquer consulta dada. Para ilustrar os recursos de monitoramento de desempenho do MongoDB, você precisará de um banco de dados com dados suficientes para que o MongoDB leve um tempo significativo para executar consultas.

Para esse fim, os exemplos ao longo deste guia referem-se a uma coleção de amostra chamada contas contendo um grande número de documentos. Cada documento representa uma conta bancária individual com um saldo de conta gerado aleatoriamente. Cada documento na coleção terá uma estrutura como esta:

An example bank account document
{
    "number": "1000-987321",
    "currency": "USD",
    "balance": 431233431
}

Este documento de exemplo contém as seguintes informações:

  • número: Este campo representa o número da conta para a conta fornecida. Nesta coleção, cada número de conta terá um prefixo de 1000- seguido de um identificador numérico crescente.
  • moeda: Este campo indica em que tipo de moeda o saldo de cada conta é armazenado. O valor de moeda de cada conta será ou USD ou EUR.
  • saldo: Isso mostra o saldo para cada conta bancária fornecida. Nesse banco de dados de exemplo, o campo saldo de cada documento terá um valor gerado aleatoriamente.

Em vez de inserir manualmente um grande número de documentos, você pode executar o seguinte código JavaScript para criar simultaneamente uma coleção chamada contas e inserir um milhão desses documentos nela:

  1. for (let i = 1; i <= 1000000; ++i) {
  2. db.accounts.insertOne({
  3. "number": "1000-" + i,
  4. "currency": i > 500000 ? "USD" : "EUR",
  5. "balance": Math.random() * 100000
  6. })
  7. }

Este código executa um loop for que roda um milhão de vezes consecutivas. Cada vez que o loop itera, ele executa um método insertOne() na coleção de contas para inserir um novo documento. Em cada iteração, o método atribui um valor ao campo number composto pelo prefixo 1000- com o valor contido no valor i para essa iteração. Isso significa que na primeira vez que esse loop iterar, o valor do campo number será definido como 1000-1; na última vez que iterar, será definido como 1000-1000000.

A moeda é sempre representada como USD para contas com números maiores que 500.000 e como EUR para contas com números menores que isso. O campo de saldo utiliza a função Math.random() para gerar um número aleatório entre 0 e 1, e então multiplica o número aleatório por 100.000 para fornecer valores maiores.

Nota: Executar este loop pode levar muito tempo, até mesmo mais de 10 minutos. É seguro deixar a operação em execução até que ela termine.

A saída informará sobre o sucesso e retornará o ObjectId do último documento que foi inserido:

Output
{ "acknowledged" : true, "insertedId" : ObjectId("61a38a4beedf737ac8e54e82") }

Você pode verificar se os documentos foram inseridos corretamente executando o método count() sem argumentos, que recuperará a contagem de documentos na coleção:

  1. db.accounts.count()
Output
1000000

Neste passo, você criou com sucesso a lista de documentos de exemplo que servirão como dados de teste usados neste guia para explicar as ferramentas que o MongoDB fornece para monitoramento de desempenho. No próximo passo, você aprenderá como verificar as estatísticas básicas de uso do servidor.

Passo 2 — Verificando Estatísticas de Uso do Servidor

O MongoDB automaticamente rastreia uma série de estatísticas de desempenho úteis, e verificar essas regularmente é uma forma fundamental de monitorar seu banco de dados. Esteja ciente de que essas estatísticas não oferecerão insights em tempo real sobre o que está acontecendo com seu banco de dados, mas podem ser úteis para determinar como o banco de dados está se comportando e se há problemas iminentes.

Aviso: Os comandos de monitoramento do MongoDB descritos neste guia retornam informações potencialmente sensíveis sobre seu banco de dados e seu desempenho. Devido a isso, alguns desses comandos requerem permissões avançadas.

Especificamente, o método serverStatus() descrito neste passo, assim como os comandos mongostat e mongotop destacados no próximo passo, todos exigem que os usuários tenham sido concedidos o papel clusterMonitor para executá-los. Da mesma forma, o método setProfilingLevel() descrito no Passo 4 requer o papel dbAdmin.

Supondo que você seguiu o tutorial pré-requisito sobre Como Segurar o MongoDB no Ubuntu 20.04 e está conectado à sua instância do MongoDB como o usuário administrativo que você criou naquele guia, você precisará conceder a ele essas funções adicionais para acompanhar os exemplos deste guia.

Primeiro, altere para o banco de dados de autenticação do seu usuário. Isso é admin no exemplo a seguir, mas conecte-se ao seu próprio banco de dados de autenticação se for diferente:

  1. use admin
Output
switched to db admin

Em seguida, execute o método grantRolesToUser() e conceda ao seu usuário a função clusterMonitor juntamente com a função dbAdmin sobre o banco de dados onde você criou a coleção accounts. O exemplo a seguir presume que a coleção accounts está no banco de dados test:

  1. db.grantRolesToUser(
  2. "AdminSammy",
  3. [
  4. "clusterMonitor",
  5. { role : "dbAdmin", db : "test" }
  6. ]
  7. )

Por favor, observe que geralmente é considerado mais seguro ter perfis de usuário dedicados a propósitos específicos. Dessa forma, nenhum usuário terá privilégios desnecessariamente amplos. Se estiver trabalhando em um ambiente de produção, você pode querer ter um usuário dedicado cujo único propósito seja monitorar o banco de dados.

O exemplo a seguir cria um usuário MongoDB chamado MonitorSammy e concede a ele as funções necessárias para você acompanhar os exemplos neste tutorial. Note que também inclui a função readWriteAnyDatabase, que permitirá a este usuário ler e escrever dados em qualquer banco de dados no cluster:

  1. db.createUser(
  2. {
  3. user: "MonitorSammy",
  4. pwd: passwordPrompt(),
  5. roles: [ { role : "dbAdmin", db : "test" }, "clusterMonitor", "readWriteAnyDatabase" ]
  6. }
  7. )

Depois de conceder ao seu usuário as funções apropriadas, retorne ao banco de dados onde sua coleção accounts está armazenada:

  1. use test
Output
switched to db test

Comece verificando as estatísticas gerais do banco de dados executando o método stats():

  1. db.stats(1024*1024)

O argumento deste método (1024*1024) é o fator de escala e indica ao MongoDB para retornar informações de armazenamento em megabytes. Se você omitir isso, os valores serão apresentados em bytes.

O método stats() retorna uma saída curta e concisa com algumas estatísticas importantes relacionadas ao banco de dados atual:

Output
{ "db" : "test", "collections" : 3, "views" : 0, "objects" : 1000017, "avgObjSize" : 80.8896048767171, "dataSize" : 77.14365005493164, "storageSize" : 24.109375, "indexes" : 4, "indexSize" : 9.9765625, "totalSize" : 34.0859375, "scaleFactor" : 1048576, "fsUsedSize" : 4238.12109375, "fsTotalSize" : 24635.703125, "ok" : 1 }

Esta saída fornece uma visão geral dos dados que esta instância do MongoDB está armazenando. As seguintes chaves retornadas nesta saída podem ser particularmente úteis:

  • A chave objects mostra o número total de documentos no banco de dados. Você pode usar isso para avaliar o tamanho do banco de dados e, quando observado ao longo do tempo, seu crescimento.
  • avgObjectSize mostra o tamanho médio desses documentos, fornecendo insights sobre se o banco de dados está operando com documentos grandes e complexos ou pequenos. Este valor é sempre mostrado em bytes, independentemente de você especificar um fator de escala.
  • As chaves collections e indexes indicam quantas coleções e índices estão atualmente definidos no banco de dados.
  • A chave totalSize indica quanto armazenamento o banco de dados ocupa no disco.

Essas informações retornadas pelo método stats() podem ajudar a ter uma ideia de quanto dados estão atualmente armazenados no seu banco de dados, mas não fornecem insights sobre seu desempenho ou problemas existentes. Para isso, o método serverStatus(), muito mais verboso, é útil:

  1. db.serverStatus()

A saída deste método é extensa e fornece uma grande quantidade de informações sobre o uso do servidor:

Output
{ "host" : "ubuntu-mongo-rs", "version" : "4.4.6", "process" : "mongod", "pid" : NumberLong(658997), "uptime" : 976, . . . "ok" : 1 }

Embora todas essas informações possam ser potencialmente úteis, este guia se concentrará em três seções em particular. Primeiro, encontre a seção connections desta saída:

Output
. . . "connections" : { "current" : 4, "available" : 51196, "totalCreated" : 4, "active" : 2, "exhaustIsMaster" : 1, "exhaustHello" : 0, "awaitingTopologyChanges" : 1 }, . . .

Cada servidor de banco de dados pode suportar apenas um número limitado de conexões ao mesmo tempo. A chave current mostra o número de clientes atualmente conectados ao banco de dados, enquanto available é o número de conexões não utilizadas restantes que o banco de dados possui disponíveis. O valor totalCreated mantém o número de conexões usadas desde o início do servidor.

A maioria das aplicações é projetada para reutilizar conexões existentes e não abrir várias conexões frequentemente. Assim, um número alto de conexões, se não for antecipado, pode ser um sinal alarmante de uma configuração incorreta de como os clientes estão acessando o servidor.

Se o alto número de conexões for antecipado pelo tipo de cargas de trabalho realizadas, você pode considerar adicionar um ou mais fragmentos a um cluster fragmentado para distribuir o tráfego entre várias instâncias do MongoDB.

Em seguida, localize a seção globalLock da saída. Esta seção está relacionada aos bloqueios globais em todo o servidor de banco de dados:

Output
. . . "globalLock" : { "totalTime" : NumberLong(975312000), "currentQueue" : { "total" : 0, "readers" : 0, "writers" : 0 }, "activeClients" : { "total" : 0, "readers" : 0, "writers" : 0 } },

O MongoDB usa bloqueios para garantir a consistência dos dados ao realizar várias operações, garantindo que duas consultas não modifiquem os mesmos dados ao mesmo tempo. Em servidores muito utilizados, há uma chance de que os bloqueios possam resultar em gargalos, com uma ou mais consultas aguardando a liberação dos bloqueios antes que possam ser executadas.

O valor currentQueue.total mostra o número de consultas aguardando os bloqueios serem liberados para que possam ser executadas. Se este valor estiver alto, significa que o desempenho do banco de dados está sendo afetado e as consultas levarão mais tempo para serem concluídas.

Isso muitas vezes decorre de muitas consultas longas mantendo os bloqueios e pode ser indicativo de um uso ineficaz de índices ou consultas mal projetadas, entre outras possibilidades.

Por último, encontre a seção opcounters:

Output
"opcounters" : { "insert" : NumberLong(10000007), "query" : NumberLong(6), "update" : NumberLong(6), "delete" : NumberLong(0), "getmore" : NumberLong(0), "command" : NumberLong(1298) },

Esta seção da saída de serverStatus() pode ajudá-lo a ter uma ideia se o servidor de banco de dados é usado principalmente para leituras ou gravações, ou se seu uso é bem equilibrado. Neste exemplo, após a inserção dos documentos de teste, o contador para operações de insert é muito maior do que para operações de query. Em um cenário da vida real, esses valores provavelmente seriam diferentes.

Bancos de dados com muitas gravações podem se beneficiar sendo escalonados horizontalmente através de sharding. Da mesma forma, bancos de dados MongoDB com muitas leituras geralmente se beneficiarão de replicação.

Essas estatísticas podem fornecer uma ideia geral de como o servidor é utilizado e se há problemas de desempenho, como filas de bloqueio longas no momento de acessá-las. No entanto, elas não fornecem informações em tempo real sobre como o servidor é utilizado. Para isso, os comandos mongostat e mongotop são ferramentas úteis.

Passo 3 — Utilizando mongostat e mongotop para Obter Estatísticas de Banco de Dados em Tempo Real

Enquanto os comandos usados para acessar as estatísticas do servidor MongoDB podem fornecer insights sobre como o servidor foi utilizado em retrospecto, eles não podem fornecer informações em tempo real sobre quais coleções estão sendo mais usadas no momento ou que tipo de consultas estão sendo executadas.

O MongoDB fornece duas ferramentas de sistema úteis para monitoramento em tempo real que analisam a atividade do banco de dados e atualizam continuamente as informações que fornecem: mongostat e mongotop. mongostat fornece uma breve visão geral do estado atual da instância do MongoDB, enquanto mongotop rastreia quanto tempo a instância gasta em operações de leitura e gravação. Ambas as ferramentas são executadas a partir da linha de comando, em vez do shell do MongoDB.

Para usar o mongostat, mantenha sua conexão atual do shell do MongoDB e abra outra janela de terminal para acessar o shell do servidor. No segundo shell do servidor, execute o comando mongostat:

  1. mongostat -u AdminSammy --authenticationDatabase admin

Como mencionado anteriormente, o mongostat requer privilégios avançados. Se você ativou a autenticação na sua instância do MongoDB e configurou um usuário com as funções apropriadas, então você terá que autenticar como esse usuário fornecendo o nome de usuário e o banco de dados de autenticação (como mostrado neste exemplo) e depois inserindo a senha quando solicitado.

Em uma configuração padrão, o mongostat imprime os contadores das consultas atualmente executadas em intervalos de um segundo:

Output
insert query update delete getmore command dirty used flushes vsize res qrw arw net_in net_out conn time *0 *0 *0 *0 0 1|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 223b 84.4k 7 Nov 28 15:40:40.621 *0 *0 *0 *0 0 2|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 224b 84.8k 7 Nov 28 15:40:41.619 *0 *0 *0 *0 0 1|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 223b 84.5k 7 Nov 28 15:40:42.621 *0 *0 *0 *0 0 3|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 365b 85.0k 7 Nov 28 15:40:43.619

Se a saída do mongostat mostrar um valor de 0 para um determinado tipo de consulta, indica que o banco de dados não está executando nenhuma operação desse tipo. Esta saída de exemplo mostra 0 para cada tipo de consulta, significando que atualmente não há consultas sendo executadas ativamente.

Você ainda deve ter sua primeira janela do terminal aberta e conectada ao shell do MongoDB. Insira mais alguns documentos de teste na coleção accounts e verifique se o mongostat irá notar a atividade:

  1. for (let i = 1; i <= 10000; ++i) {
  2. db.accounts.insertOne({
  3. "number": "2000-" + i,
  4. "currency": "USD",
  5. "balance": Math.random() * 100000
  6. })
  7. }

Este é um loop for similar ao que você executou no Passo 1. Desta vez, porém, o loop insere apenas 10000 entradas. Os números de conta são prefixados com 2000, e a moeda é sempre USD.

Enquanto os novos documentos estão sendo inseridos, verifique a saída do mongostat:

Output
. . . *0 *0 *0 *0 0 1|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 112b 42.5k 4 Nov 28 15:50:33.294 *0 *0 *0 *0 0 0|0 0.0% 38.7% 0 1.54G 210M 0|0 1|0 111b 42.2k 4 Nov 28 15:50:34.295 755 *0 *0 *0 0 1|0 0.1% 38.8% 0 1.54G 210M 0|0 1|0 154k 79.4k 4 Nov 28 15:50:35.294 2853 *0 *0 *0 0 0|0 0.4% 39.1% 0 1.54G 211M 0|0 1|0 585k 182k 4 Nov 28 15:50:36.295 2791 *0 *0 *0 0 1|0 0.7% 39.4% 0 1.54G 212M 0|0 1|0 572k 179k 4 Nov 28 15:50:37.293 2849 *0 *0 *0 0 0|0 1.0% 39.7% 0 1.54G 213M 0|0 1|0 584k 182k 4 Nov 28 15:50:38.296 745 *0 *0 *0 0 2|0 1.1% 39.8% 0 1.54G 213M 0|0 1|0 153k 79.2k 4 Nov 28 15:50:39.294 *0 *0 *0 *0 0 0|0 1.1% 39.8% 0 1.54G 213M 0|0 1|0 111b 42.2k 4 Nov 28 15:50:40.295 *0 *0 *0 *0 0 2|0 1.1% 39.8% 0 1.54G 213M 0|0 1|0 167b 42.7k 4 Nov 28 15:50:41.293 . . .

Enquanto a consulta é executada, as novas linhas retornadas por mongostat começam a mostrar valores diferentes de 0. Na coluna insert que mostra o número de consultas que estão inserindo novos dados no banco de dados, os valores foram maiores por vários segundos. Como o mongostat mostra dados em intervalos de um segundo, você pode encontrar não apenas a proporção de inserções em relação a outros tipos de operações de banco de dados, mas também a rapidez com que o banco de dados insere os novos dados. Neste exemplo, o servidor alcançou quase 3000 inserções por segundo.

Você pode usar mongostat para monitorar a carga de trabalho atual do servidor de banco de dados, agrupada por tipos de consulta. A segunda ferramenta que o MongoDB vem com — mongotop — mostra a atividade do servidor de banco de dados agrupada por coleções.

Pare mongostat de executar na sua segunda janela de terminal pressionando CTRL + C. Em seguida, execute mongotop na mesma janela. Novamente, se você tiver autenticação habilitada, precisará autenticar como um usuário com privilégios adequados:

  1. mongotop -u AdminSammy --authenticationDatabase admin

mongotop retorna uma lista de todas as coleções no banco de dados, acompanhadas pelo tempo gasto em leituras, escritas e no total dentro da janela de tempo. Similarmente ao mongostat, a saída é atualizada a cada segundo:

Output
2021-11-28T15:54:42.290+0000 connected to: mongodb://localhost/ ns total read write 2021-11-28T15:54:43Z admin.system.roles 0ms 0ms 0ms admin.system.version 0ms 0ms 0ms config.system.sessions 0ms 0ms 0ms config.transactions 0ms 0ms 0ms local.system.replset 0ms 0ms 0ms test.accounts 0ms 0ms 0ms . . .

Tente inserir mais documentos no banco de dados para ver se a atividade é registrada no mongotop. No shell do MongoDB, execute o seguinte loop for; depois de fazer isso, observe a janela do terminal com mongotop em execução:

  1. for (let i = 1; i <= 10000; ++i) {
  2. db.accounts.insertOne({
  3. "number": "3000-" + i,
  4. "currency": "USD",
  5. "balance": Math.random() * 100000
  6. })
  7. }

Desta vez, a atividade será visível nas estatísticas do mongotop:

Output
. . . ns total read write 2021-11-28T15:57:27Z test.accounts 127ms 0ms 127ms admin.$cmd.aggregate 0ms 0ms 0ms admin.system.roles 0ms 0ms 0ms admin.system.version 0ms 0ms 0ms config.system.sessions 0ms 0ms 0ms config.transactions 0ms 0ms 0ms local.system.replset 0ms 0ms 0ms ns total read write 2021-11-28T15:57:28Z test.accounts 130ms 0ms 130ms admin.$cmd.aggregate 0ms 0ms 0ms admin.system.roles 0ms 0ms 0ms admin.system.version 0ms 0ms 0ms config.system.sessions 0ms 0ms 0ms config.transactions 0ms 0ms 0ms local.system.replset 0ms 0ms 0ms . . .

Aqui, mongotop mostra que toda a atividade do banco de dados ocorreu na coleção accounts no banco de dados test e que todas as operações no intervalo de tempo foram operações de escrita. Tudo isso deve estar alinhado com a operação do loop for que você executou.

Assim como com mongostat, você pode parar mongotop de ser executado pressionando CTRL + C.

Ao ser observado durante a carga de pico, você pode usar mongotop para monitorar como a atividade do banco de dados se espalha por diferentes coleções para ajudá-lo a entender melhor seu esquema e planejar a escala. Ele também fornece insights sobre se o uso de uma coleção é mais voltado para leitura ou escrita.

Passo 4 — Usando o Profiler de Banco de Dados do MongoDB para Identificar Consultas Lentas

Os gargalos de desempenho do banco de dados podem vir de várias fontes. Embora escalar o banco de dados (horizontalmente ou verticalmente) seja frequentemente a solução para gargalos de desempenho, sua causa pode não ser realmente os limites do banco de dados, mas problemas com o esquema ou o design da consulta.

Se as consultas demorarem muito para serem concluídas, a causa pode ser um uso ineficaz de índices ou erros na própria consulta. Consultas de longa duração frequentemente passam despercebidas durante o desenvolvimento de aplicativos, geralmente porque os conjuntos de dados de teste são muito pequenos ou as condições são diferentes das de produção.

Você poderia potencialmente encontrar o culpado executando manualmente consultas de teste e verificando quais delas têm desempenho inferior, embora isso seja muito tedioso. Felizmente, a ferramenta de perfil do banco de dados do MongoDB pode fazer isso automaticamente.

O profiler do banco de dados do MongoDB pode registrar consultas e estatísticas sobre sua execução quando elas atendem a certas condições. A mais importante dessas condições é o tempo de execução da consulta: se uma consulta levar mais tempo do que um tempo especificado para ser executada, o profiler automaticamente sinalizará essa consulta como problemática. Usando o profiler, você pode identificar quais consultas têm desempenho ruim e então focar em corrigir esses problemas específicos.

Antes de usar o profiler, execute a seguinte consulta. Esta consulta irá recuperar uma das contas que você inseriu, embora não seja tão simples quanto parece à primeira vista:

  1. db.accounts.find({"number": "1000-20"})

O comando irá recuperar a conta exata que você solicitou:

Output
{ "_id" : ObjectId("61a38fd5eedf737ac8e54e96"), "number" : "1000-20", "currency" : "EUR", "balance" : 24101.14770458518 }

Você pode ter notado que a consulta não foi executada imediatamente e que levou um momento ou dois para o MongoDB encontrar a conta. Em uma aplicação do mundo real, pode haver muitos tipos de consultas que têm desempenho ruim, e você pode não perceber seu desempenho insatisfatório na prática.

Você pode configurar o MongoDB para ajudá-lo a identificar quais consultas levam mais tempo do que o esperado. Para fazer isso, primeiro ative o profiler executando o seguinte comando:

  1. db.setProfilingLevel(1, { slowms: 100 })

O método setProfilingLevel() recebe dois argumentos. O primeiro é o nível de perfil, que pode ser 0, 1 ou 2:

  • 0 desativa o profiler
  • 1 ativa o profiler apenas em consultas lentas que atendem à condição
  • 2 habilita o profiler para todas as consultas

Neste exemplo, o profiler irá analisar consultas que executam por mais de 100 milissegundos, conforme definido pelo segundo argumento, { slowms: 100 }.

Nota: O uso do profiler degrada o desempenho, pois o MongoDB agora deve analisar consultas além de executá-las. Deve ser usado com moderação ao monitorar gargalos de desempenho.

É possível personalizar ainda mais o conjunto de consultas que o profiler irá registrar, configurando-o para perfilar apenas um certo percentual de consultas ou filtrando por tipo de consulta. Para aprender mais sobre como ter maior controle sobre o profiler, consulte a documentação oficial sobre o assunto.

Este método retornará uma mensagem de sucesso:

Output
{ "was" : 0, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }

A partir de agora, o perfilamento do banco de dados estará habilitado e o MongoDB irá monitorar ativamente cada consulta que você executar para encontrar aquelas que levam mais de 100 milissegundos para serem concluídas.

Tente isso executando algumas consultas diferentes. Primeiro, use o comando count para encontrar o número de documentos na coleção accounts:

  1. db.accounts.count()

Este comando retornará rapidamente o número de documentos na coleção:

Output
1020000

Em seguida, tente procurar as três primeiras contas bancárias que aparecem na coleção:

  1. db.accounts.find().limit(3)

Novamente, o banco de dados retornará os resultados rapidamente:

Output
{ "_id" : ObjectId("61ef40640f2ba52efc56ee17"), "number" : "1000-1", "currency" : "EUR", "balance" : 25393.132960293842 } { "_id" : ObjectId("61ef40640f2ba52efc56ee18"), "number" : "1000-2", "currency" : "EUR", "balance" : 63629.42056192393 } { "_id" : ObjectId("61ef40640f2ba52efc56ee19"), "number" : "1000-3", "currency" : "EUR", "balance" : 75602.12331602155 }

Por fim, execute novamente a consulta de pesquisa para a conta bancária específica:

  1. db.accounts.find({"number": "1000-20"})

Esta consulta retornará o resultado, mas, como antes, levará um momento ou dois a mais do que as operações anteriores:

Output
{ "_id" : ObjectId("61a38fd5eedf737ac8e54e96"), "number" : "1000-20", "currency" : "EUR", "balance" : 24101.14770458518 }

O profiler não produz nenhuma saída própria, mesmo que a consulta seja visivelmente mais lenta. Em vez disso, os detalhes sobre operações lentas são registrados em uma coleção especial dentro do banco de dados chamada system.profile. Esta coleção é uma coleção com limitação de tamanho que nunca excede 1 MB. Isso significa que sempre conterá uma lista apenas das consultas lentas mais recentes.

Para recuperar informações sobre consultas identificadas pelo profiler, você precisa consultar a coleção system.profile de uma maneira como esta:

  1. db.system.profile.find().sort({ "ts" : -1 }).pretty()

Esta consulta usa o método find(), como de costume. Também inclui uma cláusula sort que contém { "ts" : -1 } como argumento. Isso classificará o conjunto de resultados com as consultas mais recentes primeiro. Por último, o método pretty() no final exibirá a saída em um formato mais legível.

Cada consulta lenta é representada como um documento regular, e system.profile é como qualquer outra coleção regular. Isso significa que você pode filtrar os resultados, classificá-los e até mesmo usá-los em pipelines de agregação para reduzir ainda mais ou analisar a lista de consultas identificadas pelo profiler.

Observe que o resultado consiste apenas em um único documento. As outras duas consultas foram executadas rápido o suficiente para não acionar o profiler:

Output
{ "op" : "query", "ns" : "test.accounts", "command" : { "find" : "accounts", "filter" : { "number" : "1000-20" }, . . . }, "nreturned" : 1, "keysExamined" : 0, "docsExamined" : 1030000, . . . "millis" : 434, "planSummary" : "COLLSCAN", . . . }

Esta saída fornece diversos detalhes sobre a execução da consulta lenta:

  • A chave op mostra que tipo de operação esta informação representa. Aqui, é uma consulta, já que representa uma operação na qual você usou o find() para recuperar dados do banco de dados.
  • A chave ns indica em que banco de dados e coleção a operação estava envolvida. Como a saída mostra, esta operação consultou a coleção accounts no banco de dados test.
  • A chave command fornece mais informações sobre a própria consulta. Neste caso, o subchave filter contém todo o documento de filtro. Usando as informações provenientes dos campos op e command, você pode reconstruir a consulta em questão.
  • No campo millis, você encontrará o tempo exato que levou para concluir a consulta. Neste exemplo, quase meio segundo.
  • O campo docsExamined fornece o número de documentos examinados para retornar o conjunto de resultados.
  • nreturned representa o número de documentos que a consulta retornou. Neste exemplo, apenas um único documento foi retornado de mais de um milhão examinados.
  • O planSummary mostra o método que o MongoDB usou para executar a consulta. COLLSCAN corresponde a uma varredura completa da coleção, o que significa que ele percorreu cada documento na coleção um por um para encontrar a conta bancária correspondente.

Todos juntos, estas informações destacam a necessidade de um índice que possa ajudar o MongoDB a executar esta consulta mais rapidamente. O banco de dados teve que percorrer toda a coleção para encontrar um único documento, como indicado pela grande diferença entre o número de documentos examinados e retornados, bem como a estratégia de execução.

Neste exemplo particular, criar um índice para apoiar consultas que filtram dados com base no campo number proporcionaria um impulso imediato ao desempenho desses tipos de consultas. Em cenários reais, as soluções para consultas lentas podem diferir e depender da consulta exata que está causando problemas.

Para encerrar a sessão de perfil, você pode desativar o profiler definindo o nível de perfil para zero:

  1. db.setProfilingLevel(0)

A operação será bem-sucedida com uma mensagem de confirmação:

Output
{ "was" : 1, "slowms" : 100, "sampleRate" : 1, "ok" : 1 }

Agora o banco de dados retorna à operação normal sem o perfilamento acontecendo nos bastidores.

Sempre que você suspeitar que consultas lentas possam estar tendo um impacto negativo no desempenho do seu banco de dados, você pode usar o profiler do banco de dados para encontrá-las e entender melhor sua estrutura e como são executadas. Com estas informações, você estará melhor equipado para ajustá-las e melhorar seu desempenho.

Conclusão

Ao seguir este guia, você aprendeu como encontrar as estatísticas do servidor MongoDB e como usar ferramentas de diagnóstico como mongotop, mongostat, bem como o mecanismo de perfil do banco de dados do MongoDB. Você pode usá-los para ter uma melhor compreensão da carga de trabalho do seu banco de dados, determinar quais coleções são as mais ativas e se o servidor realiza predominantemente gravações ou leituras. Você também pode identificar consultas lentas que estão impactando o desempenho do MongoDB para substituí-las por consultas mais eficientes.

Essas são apenas algumas das ferramentas e técnicas que você pode usar para monitorar a saúde e o desempenho da sua instalação do MongoDB e agir sobre elas. Cada uma dessas ferramentas pode ser ainda mais configurada e personalizada para fornecer informações mais direcionadas sobre o desempenho do servidor. Encorajamos você a estudar a documentação oficial do MongoDB para aprender mais sobre técnicas que você pode usar para monitorar o desempenho do servidor e agir sobre ele.

Source:
https://www.digitalocean.com/community/tutorials/how-to-monitor-mongodb-s-performance