Guia abrangente para otimizar o desempenho do MongoDB
Avalie esse Artigo
O MongoDB é conhecido por seu alto desempenho e escalabilidade, tornando-o uma escolha popular entre os bancos de dados NoSQL. No entanto, para aproveitar ao máximo seu potencial, é essencial ajustar a implantação do MongoDB. Este guia descreve várias estratégias e práticas recomendadas para melhorar o desempenho do MongoDB, abrangendo tudo, desde a identificação de gargalos até a otimização de queries e hardware.
Antes de mergulhar no ajuste de desempenho, é crucial entender sua carga de trabalho. O desempenho do MongoDB pode variar significativamente com base no fato de seu aplicativo ter muita leitura, muitas gravações ou uma mistura balanceada. Utilize ferramentas como o Atlas Profilerdo MongoDB ou o
mongostat
de código aberto para analisar suas operações de banco de dados e obter insights sobre seu volume de trabalho.A indexação eficaz é uma das maneiras mais impactantes de melhorar o desempenho da consulta no MongoDB. Veja as principais práticas:
- Criar índices relevantes: adapte índices para corresponder aos padrões de query do seu aplicativo. Use o método [explain() para entender o comportamento da query e otimizá-la adequadamente.
db.collection.find({ field: value }).explain("executionStats")
Você também pode obter essas informações do MongoDB Compass com saída sofisticada, conforme mostrado abaixo.
- Evite a indexação excessiva: embora os índices melhorem a velocidade da query, eles podem impedir operações de gravação e consumir espaço em disco adicional. Revise e remova regularmente índices não utilizados ou desnecessários.
db.collection.dropIndex("indexName")
- Use índices compostos: para queries envolvendo vários campos, os índices compostos podem aumentar significativamente o desempenho.
db.collection.createIndex({ field1: 1, field2: -1 })
Otimizar seus padrões de consulta é crucial para reduzir o tempo de execução e o uso de recursos:
- Projeção: use a projeção para limitar os campos retornados por suas queries, minimizando a transferência de dados e a carga de processamento. Além disso, é melhor excluir _id com 0 (falso) se não for um campo pertencente ao aplicação — ou seja, um campo gerado automaticamente pelo MongoDB.
db.collection.find({ field: value }, { field1: 1, field2: 1 })
- Framework deaggregation : aproveite o framework de agregação do MongoDB para processamento de dados complexos. Certifique-se de que as agregações utilizem campos indexados sempre que possível.
db.collection.aggregate([ { $match: { field: value } }, { $group: { _id: "$field", total: { $sum: "$amount" } } } ])
- Evite $where: o
$where
operador pode ser lento e consome muitos recursos. Use-o com moderação e somente quando necessário. Em vez disso, o uso de $expr com operadores de agregação que não usam JavaScript (ou seja, operadores acumulador não $function e não $) é mais rápido do que $where porque não executa JavaScript e é preferível, quando possível. No entanto, se você precisar criar expressões personalizadas, $function é preferível a $where.
O hardware no qual o MongoDB é executado desempenho um papel crucial em seu desempenho:
- RAM: o MongoDB depende muito da RAM para armazenar conjuntos de trabalho. Se o seu conjunto de dados exceder a RAM disponível, considere atualizar a memória.
- Armazenamento: utilize SSDs para armazenamento para melhorar a taxa de transferência de E/S e as velocidades de acesso a dados.
- Rede: certifique-se de que a largura de banda e a latência da rede sejam suficientes, especialmente em sistemas distribuídos.
Replicação e sharding O MongoDB oferece suporte à replicação e ao sharding para melhorar a disponibilidade e a escalabilidade:
- Replicação: isso garante redundância de dados e alta disponibilidade. Configure as configurações de preferência de leitura para rotear com eficiência as operações de leitura entre réplicas.
rs.initiate()
A seguir estão os métodos de leitura disponíveis com o MongoDB, que você pode configurar no nível do aplicativo.
- primary: lê somente do primary
- primaryPreferred: leituras do primário, se disponíveis, caso contrário, de um secundário
- secundário: leituras somente de um secundário
- secondaryPreferred: Lê de um secundário, se disponível, caso contrário, do primário
- mais próximo: Lê a partir do nó mais próximo com base na latência da rede e na integridade operacional
Exemplo: definir read preferences no código do aplicativo (Node.js)
1 const MongoClient = require('mongodb').MongoClient; 2 const uri = "mongodb://host1,host2,host3/?readPreference=secondaryPreferred"; 3 MongoClient.connect(uri, function(err, client) { 4 const db = client.db('test'); 5 // Perform operations 6 });
- Fragmentação: distribui dados entre vários servidores e é crucial para gerenciar grandes conjuntos de dados e operações de alto rendimento. Escolha uma chave de shard que distribua uniformemente a carga de dados e query.
sh.enableSharding("mydatabase") sh.shardCollection("mydatabase.mycollection", { shardKey: 1 })
Escolher uma chave de shard no MongoDB pode afetar significativamente o desempenho, dependendo se seu volume de trabalho é de leitura ou gravação. Aqui estão algumas diretrizes para selecionar uma chave de shard com base em sua carga de trabalho:
Seleção de chave de shard: escolha uma chave de shard que distribua uniformemente as operações de leitura entre os shards.
Considerações: Use um campo de alta cardinalidade que garanta a distribuição uniforme de leituras. Evite chaves de shard que podem causar pontos quentes onde a maioria das leituras tem como alvo um único shard.
Exemplo: use um ID do usuário de usuário se as queries relacionadas ao usuário forem comuns.
sh.shardCollection("mydatabase.mycollection", { userID: 1 })
Seleção de chave de shard: escolha uma chave de shard que equilibre a carga de gravação entre shards.
Considerações: Use um campo que muda com frequência e garante distribuição uniforme de escrita. Evite aumentar monotonicamente as chaves (por exemplo, carimbos de data/hora), pois elas podem fazer com que um único fragmento seja um gargalo.
Exemplo: use uma chave de fragmento com hash para distribuir as gravações uniformemente se você não conseguir obter uma chave de shard exclusiva.
sh.shardCollection("mydatabase.mycollection", { hashedField: "hashed" })
Considerações adicionais: Monitorar e ajustar: monitore continuamente o desempenho e ajuste as chaves de shard, se necessário.
Indexação: certifique-se de que os índices estejam alinhados com a chave de shard para obter o desempenho ideal da consulta. Ao selecionar a chave de shard apropriada e considerar a natureza do seu volume de trabalho, você pode otimizar o sistema do MongoDB para operações de leitura e gravação.
O monitoramento e a manutenção regulares são vitais para o desempenho sustentável:
- Ferramentas de monitoramento : utilize o MongoDB Atlas, mongostat e mongotop para monitorar o desempenho do banco de dados de dados e o uso de recursos.
mongostat --host <host> mongotop --host <host>
- Manutenção de rotina : compactar regularmente coleções, reparar bancos de dados e reequilibrar fragmentos para garantir o desempenho ideal.
db.repairDatabase()
A escolha da preocupação de gravação pode influenciar o desempenho e a durabilidade dos dados.
Uma write concern menor (por exemplo, w: 0) pode melhorar o desempenho reduzindo a latência da operação de escrita. No entanto, arrisca a durabilidade dos dados.
Impacto na latência
Preocupação de gravação inferior (por exemplo, w: 0):
Redução da latência:
- O cliente não espera nenhuma confirmação do servidor.
- A operação é enviada ao servidor e considerada concluída do ponto de vista do cliente.
- Não há latência de ida e volta da rede, pois não há necessidade de o servidor responder.
Troca:
- Há um risco maior de perda de dados, pois o cliente não recebe nenhuma confirmação de sucesso na gravação.
- Ele é adequado para dados não críticos ou cenários em que é necessária uma alta taxa de transferência de gravação com latência mínima.
Preocupação de gravação maior (por exemplo, w: 1 ou w: "maioria"):
Aumento da latência
- O cliente aguarda a confirmação do servidor.
- Para w: 1, aguarda a confirmação do nó primário.
- Para w: "maioria", aguarda a confirmação da maioria dos nós do conjunto de réplicas.
- A latência de ida e volta da rede e o tempo de processamento do servidor aumentam a latência geral.
- Maior durabilidade e consistência de dados.
- Garante que a operação de gravação seja replicada e reconhecida.
db.collection.insertOne({ field: "value" }, { writeConcern: { w: 1 } })
A escolha da read preference pode influenciar o desempenho e a disponibilidade dos dados.
Desempenho: a distribuição de operações de leitura para nós secundários pode melhorar o desempenho reduzindo a carga no primary. Para distribuir com êxito as operações de leitura para nós secundários e, assim, melhorar o desempenho, é necessário definir a preferência de leitura no MongoDB. Aqui estão exemplos de como configurar read preferences:
db.getMongo().setReadPref("secondaryPreferred")
URI de conexão
mongodb://host1,host2,host3/?readPreference=secondaryPreferred
** Exemplo de código do aplicativo (NodeJS) **
1 const MongoClient = require('mongodb').MongoClient; 2 const uri = "mongodb://host1,host2,host3/?readPreference=secondaryPreferred"; 3 MongoClient.connect(uri, function(err, client) { 4 const db = client.db('test'); 5 // Perform operations 6 })
Ao definir a read preference como secondaryPreferred, você direciona as operações de leitura para nós secundários quando elas estão disponíveis, reduzindo a carga no nó primary e melhorando o desempenho geral.
Verificações para identificar as razões comuns para problemas de desempenho:
- Execute o mongotop e o mongostat e verifique qual namespace está causando o problema.
- Nível do sistema - verifique se há replicação primária. Há algum atraso e como está a oplog window?
- Nível do aplicativo — verifique se há carregamentos em lote no nível do aplicativo.
- Qualquer queries lentas (com currentOp ())?
- Existem índices adequados?
- Cluster fragmentado — a maioria das queries usa a chave de shard?
- WT cache? Algum despejo?
- Você vê contenção de gravação?
- Abrir arquivos ( ulimit -a ) - 65000
- Verifique se o processo mongod por si só causa carga no servidor ou qualquer outro processo.
- top ou htop: Monitore o uso da CPU e da memória do mongod e de outros processos.
- ps e grep: execute
ps aux | grep mongod
para visualizar o usodo recurso mongod. - iostat: use
iostat -x 1 10
para verificar as métricas de E/S do disco. - vmstat: Execute o
vmstat 1 10
para capturas instantâneas do desempenho geral do sistema.
A contenção de escrita no MongoDB pode ser identificada pelos seguintes indicadores:
Altas porcentagens de bloqueio : Use o mongostat para monitorar porcentagens de bloqueio . Valores altos indicam contenção. Operações de gravação lenta: Verifique operações de gravação lenta usando db.currentOp() que pode indicar contenção. Conflitos deescrita frequentes: revise os registros em busca de mensagens sobre conflitos de escrita ou rejeições.
Aumento da latência: observe o aumento da latência em operações ou aplicativos de escrita pesada.
Comando de exemplo para monitorar porcentagens de bloqueio:
mongostat --host <hostname>
Projetar o esquema adequadamente, como usar índices apropriados e evitar pontos de acesso com gravações distribuídas, pode ajudar a reduzir a contenção de gravação.
Obter o desempenho ideal do MongoDB envolve uma abordagem abrangente, incluindo otimização de queries, indexação adequada, recursos de hardware suficientes e monitoramento contínuo. Ao implementar as estratégias descritas neste guia, você pode melhorar significativamente a eficiência e a capacidade de resposta do MongoDB deployment, garantindo que ele atenda às solicitações de seus aplicativos.
Principais comentários nos fóruns
Srinivas_MutyalaSrinativas Mutyala2 trimestres atrás
Olá comunidade !!!
Estou buscando suas sugestões/ feedback sobre este artigo.