Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Saiba por que o MongoDB foi selecionado como um líder no 2024 Gartner_Magic Quadrupnt()
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Produtoschevron-right
MongoDBchevron-right

Dados da primavera desbloqueados: técnicas de otimização de desempenho com o MongoDB

Ricardo Mello5 min read • Published Dec 04, 2024 • Updated Dec 04, 2024
SpringMongoDBÍndicesJava
APLICATIVO COMPLETO
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Sim, já vi! Assim como no segundo artigo, você está aqui porque usou o tópico inicial, certo? Para recapitular: no primeiro artigo, abordamos como começar a usar o MongoDB e o Spring Data, explorando a diferença entre MongoTemplate e MongoRepository e quando usar um ou outro. Na segunda parte, demos um passo adiante ao explorar queries avançadas e aprender conceitos poderosos que a Spring oferece. Por fim (mas não menos importante), vamos ver como otimizar nosso aplicação por meio de estratégias como preferências de leitura e índices.

Pré-requisitos

Por que focar na velocidade do MongoDB ?

Melhorar o desempenho no MongoDB é crucial para garantir o acesso rápido e eficiente aos dados e melhorar a experiência do usuário. Ao otimizar estratégias, podemos reduzir a latência, aumentar a taxa de transferência e escalar melhor os aplicativos à medida que eles crescem.

Melhorando o desempenho com índices

Você provavelmente já deve ter escutado incontáveis vezes que os índices são essenciais para alcançar alta performance em suas queries, não é mesmo? No entanto, é importante lembrar que os índices vêm com certas regras, e mesmo índices não utilizados podem impacto negativamente seu banco de dados de dados. Em collections com uma alta frequência de gravações em comparação com as leituras, a manutenção de índices pode ser um desafio, porque cada gravação exige atualizá-las.
Você pode estar se perguntado:Okay, but how do I know when to create an index or not?“” Bem, geralmente criamos índices quando nosso aplicação executa queries com frequência no mesmo campo. Em nosso aplicação, vamos revisar a TransactionRepository classe e dar uma olhada no métodofindByTransactionType(tipostring de string):
1@Repository
2public interface TransactionRepository extends MongoRepository<Transaction, String> {
3
4 List<Transaction> findByTransactionType(String type);
5 // Other methods ..
6}
Este método é responsável por recuperar transações por tipo. Para entender o custo dessa query, podemos executar o comando explain():
1db.transactions.find({"transactionType": "Debit"}).explain()
Ou, no nosso caso, executaremos uma query diretamente usando o Spring. Em CustomerService, crie o seguinte método:
1public String explain() {
2
3 MongoCollection<Document> collection = mongoOperations.getCollection("transactions");
4
5 Document query = new Document("transactionType", "Debit");
6 Document explanation = collection.find(query).explain();
7
8 logger.info(explanation.toJson());
9 return explanation.toJson();
10}
O explain() comando fornece o plano de execução da query, detalhando como o MongoDB processa a query. No nosso caso, como não temos um índice, ele retorna um COLLSCAN (verificação de collection).
explicar o plano detalhando como o MongoDB processa a query

Índice de campo único

Para otimizar isso, vamos criar um índice para essa query. Tradicionalmente, criamos o índice da seguinte maneira:
1db.transactions.createIndex({"transactionType": 1})
No entanto, como estamos explorando as opções do Spring, criaremos o índice de uma maneira diferente. Para fazer isso, basta navegar até a Transaction classe (que representa nossa coleção) e anotar o campo desejado com a @Indexed anotação:
1import lombok.Data;
2import org.springframework.data.annotation.Id;
3import org.springframework.data.mongodb.core.index.Indexed;
4import org.springframework.data.mongodb.core.mapping.Document;
5
6@Document(collection = "transactions")
7@Data
8public class Transaction {
9
10 @Indexed
11 private String transactionType;
12
13 // Other fields
14}
Para que isso funcione, precisamos habilitar a criação automática de índice nas propriedades do aplicação adicionando a seguinte configuração:
1spring:
2 data:
3 mongodb:
4 auto-index-creation: true
Aviso: Embora essa seja uma maneira conveniente de criar índices durante o desenvolvimento, é importante ter cuidado em ambientes de produção. A criação de índices automáticos pode fazer com que a inicialização do aplicação seja pausada enquanto o índice está sendo criado, o que pode causar atrasos ou problemas de disponibilidade se não for tratado com cuidado. Para cenários de produção, considere a criação de índices explicitamente durante um processo controlado fora do ciclo de vida do aplicação .

Índice Composto

Continuando com nossa análise de índices, agora temos índices compostos. Como o nome sugere, esses índices combinam mais de um campo para fins de query. Vamos presumir que temos uma query que pesquisa tanto o tipo de transação quanto a moeda:
1@Repository
2public interface TransactionRepository extends MongoRepository<Transaction, String> {
3
4 List<Transaction> findByTransactionTypeAndCurrency(String type, String currency);
5
6 // Other methods
7}
Para otimizar essa query, poderíamos criar o índice composto da seguinte maneira:
1@CompoundIndex(name = "type_currency", def = "{'transactionType': 1, 'currency': 1}")
2@Data
3public class Transaction {
4 // fields
5}
Unique indexes
A @Indexed interface inclui um unique() método, que é definido como false por padrão. Isso significa que qualquer campo anotado com @Indexed não imporá exclusividade por padrão. No entanto, podemos especificar que queremos que o campo seja exclusivo.
Imagine que, em nossa Transaction classe , tenhamos um campo chamado authCode, responsável por garantir que cada transação seja única. Podemos anotar a classe da seguinte maneira:
1public class Transaction {
2 @Indexed(unique = true)
3 private String authCode;
4}
Essa anotação garante que a transactions coleção não terá nenhum valor deauthCode duplicado. Se um código duplicado for fornecido, o MongoDB lançará a seguinte exceção:
1com.mongodb.MongoWriteException - E11000 duplicate key error collection

TTL/índice parcial

Suponha que temos uma função em nosso aplicação que executa uma query para localizar todas as transações com mais de 40 dias com status de "COMPLETED " ou "SUCCESS " e executa um comando de exclusão. Neste caso, teriamos duas etapas:
  1. Filtre todas as transações neste estado.
  2. Execute uma operação de exclusão nesses itens.
Isso pode ser caro para o seu aplicação. Uma alternativa é usar o índice TTL, que expira automaticamente os documentos após um determinado período de tempo. Podemos dizer ao nosso aplicação:
"Ei, gostaria que você exclua todos os registros que foram criados há mais de 40 dias e estão no status "SUCCESS " ou "COMPLETED ""
1public class Transaction {
2
3 @Indexed(
4
5 name = "PartialIndex",
6
7 expireAfterSeconds = 3456000, //40 days
8
9 partialFilter = "{ 'status': { $in: ['SUCCESS', 'COMPLETED'] } }"
10
11 )
12
13 private LocalDateTime createdAt;
14
15}
Dessa forma, o aplicação expirará (excluirá) as transações que atenderem a esse filtro.

Otimizando leituras com ReadPreference

O uso de ReadPreference pode melhorar a latência e o desempenho ao direcionar as leituras para réplicas secundárias mais próximas, reduzir a carga no nó primário e otimizar a distribuição de dados em sistemas distribuídos geograficamente.
Cluster do conjunto de réplicas
Conforme mostrado na imagem acima, por padrão, todas as operações de gravação ocorrem no nó primário, enquanto as operações de leitura podem ser direcionadas para nós secundários. Existem vários modos de preferência de leitura , como:
Vamos Go voltar à nossa TransactionRepository classe e marcar o métodofindByTransactionType para executar a pesquisa usando o modosecondaryPreferred :
1@Repository
2public interface TransactionRepository extends MongoRepository<Transaction, String> {
3 @ReadPreference("secondaryPreferred")
4 List<Transaction> findByTransactionType(String type);
5}
Outra alternativa é aplicar o modo a todo o aplicação por meio das configurações de conexão. No MongoConfig, você pode configurar o modo de preferência de leitura globalmente. Veja como você pode fazer isso:
1@Configuration
2public class MongoConfig {
3 @Bean
4 public MongoClient mongoClient() {
5 MongoClientSettings settings = MongoClientSettings.builder()
6 .applyConnectionString(new ConnectionString(connectionString))
7 .readPreference(ReadPreference.nearest())
8 .build();
9 return MongoClients.create(settings);
10 }

Conclusão

Nesta terceira e última parte da série Spring Data Unlocked , aprenderam como criar índices diretamente pelo aplicação, ajustar as preferências de leitura com o ReadPreference e otimizar o desempenho de nossas queries. O código completo do aplicação está disponível no repositório mongodb-developer.
Para obter mais informações sobre como melhorar o desempenho da query com índices, acesse a documentação sobre índices.
Se tiver alguma dúvida, entre em contato conosco por meio da MongoDB Community .
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Artigo
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

Definir preocupações globais de leitura e gravação no MongoDB 4.4


Sep 23, 2022 | 7 min read
Notícias e Anúncios

Interrompendo o desenvolvimento do driver Swift do MongoDB


Sep 11, 2024 | 1 min read
Início rápido

Introdução ao MongoDB e Sanic


Jul 12, 2024 | 5 min read
Artigo

Guia abrangente para otimizar o desempenho do MongoDB


Jul 09, 2024 | 7 min read
Sumário