Quando estamos trabalhando com um banco de dados, a otimização é crucial e fundamental em termos de desempenho e eficiência do aplicativo. Da mesma forma, no Azure Cosmos DB, a otimização é crucial para maximizar a eficiência, minimizar custos e garantir que seu aplicativo escale efetivamente. Abaixo estão algumas das melhores práticas com exemplos de codificação para otimizar o desempenho no Azure Cosmos DB.
1. Seleção da Chave de Partição Certa
Escolher uma chave de partição apropriada é vital para bancos de dados distribuídos como Cosmos DB. Uma boa chave de partição garante que os dados sejam distribuídos uniformemente entre as partições, reduzindo pontos de sobrecarga e melhorando o desempenho.
A seleção de uma chave de partição é simples, mas muito importante no momento do design no Azure Cosmos DB. Uma vez nós selecionamos a chave de partição, não é possível alterá-la no local.
Melhor Prática
- Selecione uma chave de partição com alta cardinalidade (muitos valores únicos).
- Garanta que distribua a leitura e gravação de forma equilibrada.
- Mantenha dados relacionados juntos para minimizar consultas entre partições.
Exemplo: Criando um Contêiner com uma Chave de Partição Ótima
var database = await cosmosClient.CreateDatabaseIfNotExistsAsync("YourDatabase");
var containerProperties = new ContainerProperties
{
Id = "myContainer",
PartitionKeyPath = "/customerId" // Partition key selected to ensure balanced distribution
};
// Crie o contêiner com uma taxa de transferência provisionada de 400 RU/s
var container = await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400);
2. Indexação Adequada Use Indexação
No Azure Cosmos DB, índices são aplicados a todas as propriedades por padrão, o que pode ser benéfico, mas pode resultar em custos aumentados de armazenamento e RU/s. Para melhorar o desempenho das consultas e minimizar despesas, considere personalizar a política de indexação. O Cosmos DB suporta três tipos de índices: Índices de Intervalo, Índices Espaciais e Índices Compostos. Use o tipo adequado com sabedoria.
Melhores Práticas
- Exclua campos desnecessários da indexação.
- Use índices compostos para consultas de múltiplos campos.
Exemplo: Política de Indexação Personalizada
{
"indexingPolicy": {
"automatic": true,
"indexingMode": "consistent", // Can use 'none' or 'lazy' to reduce write costs
"includedPaths": [
{
"path": "/orderDate/?", // Only index specific fields like orderDate
"indexes": [
{
"kind": "Range",
"dataType": "Number"
}
]
}
],
"excludedPaths": [
{
"path": "/largeDataField/*" // Exclude large fields not used in queries
}
]
}
}
Exemplo: Adicionando um Índice Composto para Consultas Otimizadas
{
"indexingPolicy": {
"compositeIndexes": [
[
{ "path": "/lastName", "order": "ascending" },
{ "path": "/firstName", "order": "ascending" }
]
]
}
}
Você pode ler mais sobre tipos de indexação aqui.
3. Otimize Consultas
A consulta eficiente é crucial para minimizar unidades de requisição (RU/s) e melhorar o desempenho no Azure Cosmos DB. O custo de RU/s depende da complexidade e do tamanho da consulta.
A utilização de executores em massa pode reduzir ainda mais os custos, diminuindo os RUs consumidos por operação. Essa otimização ajuda a gerenciar o uso de RU de forma eficaz e reduz suas despesas gerais com o Cosmos DB.
Melhores Práticas
- Use consultas
SELECT
em quantidades limitadas, recupere apenas as propriedades necessárias. - Evite consultas entre partições fornecendo a chave de partição em sua consulta.
- Use filtros em campos indexados para reduzir os custos de consulta.
Exemplo: Buscar Registro do Cliente
var query = new QueryDefinition("SELECT c.firstName, c.lastName FROM Customers c WHERE c.customerId = @customerId")
.WithParameter("@customerId", "12345");
var iterator = container.GetItemQueryIterator<Customer>(query, requestOptions: new QueryRequestOptions
{
PartitionKey = new PartitionKey("12345") // Provide partition key to avoid cross-partition query
});
while (iterator.HasMoreResults)
{
var response = await iterator.ReadNextAsync();
foreach (var customer in response)
{
Console.WriteLine($"{customer.firstName} {customer.lastName}");
}
}
4. Ajuste dos Níveis de Consistência
Os níveis de consistência definem modos operacionais específicos projetados para atender garantias relacionadas à velocidade. Existem cinco níveis de consistência (Forte, Estabilidade Limitada, Sessão, Prefixo Consistente e Eventual) disponíveis no Cosmos DB. Cada nível de consistência impacta latência, disponibilidade e throughput.
Melhores Práticas
- Use consistência de sessão para a maioria dos cenários para equilibrar desempenho e consistência de dados.
- A consistência forte garante a consistência dos dados, mas aumenta o RU/s e a latência.
Exemplo: Definindo o Nível de Consistência
var cosmosClient = new CosmosClient(
"",
"",
new CosmosClientOptions
{
// Defina a consistência como "Sessão" para desempenho equilibrado
ConsistencyLevel = ConsistencyLevel.Session
});
Saiba mais sobre o nível de consistência aqui.
5.Use Provisioned Throughput (RU/s) and Auto-Scale Wisely
O provisionamento de throughput é um fator-chave para alcançar eficiência de custos e desempenho ótimo no Azure Cosmos DB. O serviço permite configurar o throughput de duas maneiras:
- RU/s Fixo: Um nível constante e predefinido de Unidades de Requisição por segundo (RU/s), adequado para cargas de trabalho com demandas de desempenho consistentes.
- Auto-Scale: Uma opção dinâmica que ajusta automaticamente o throughput com base em flutuações de carga de trabalho, fornecendo escalabilidade e evitando superprovisionamento durante períodos de baixa atividade.
Escolher o modelo de throughput apropriado ajuda a equilibrar as necessidades de desempenho com a gestão de custos de forma eficaz.
Melhores Práticas
- Para cargas de trabalho previsíveis, provisione o throughput manualmente.
- Use o auto-scale para cargas de trabalho imprevisíveis ou com picos de demanda.
Exemplo: Provisionamento de Throughput com Auto-Scale
var throughputProperties = ThroughputProperties.CreateAutoscaleThroughput(maxThroughput: 4000); // Autoscale up to 4000 RU/s
var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
Id = "autoscaleContainer",
PartitionKeyPath = "/userId"
}, throughputProperties);
Exemplo: Configurando Manualmente RU/s Fixo para Cargas de Trabalho Estáveis
var container = await database.CreateContainerIfNotExistsAsync(new ContainerProperties
{
Id = "manualThroughputContainer",
PartitionKeyPath = "/departmentId"
}, throughput: 1000); // Fixed 1000 RU/s
6.Aproveite o Feed de Mudanças para Processamento Eficiente em Tempo Real
O feed de alterações permite o processamento em tempo real, baseado em eventos, capturando automaticamente as mudanças no banco de dados, eliminando a necessidade de pesquisa. Isso reduz a sobrecarga de consultas e aprimora a eficiência.
Melhores Práticas
- Use o feed de alterações em cenários onde mudanças de dados em tempo real precisam ser processadas (por exemplo, análises em tempo real, notificações, alertas).
Exemplo: Lendo do Feed de Alterações
var iterator = container.GetChangeFeedIterator(
ChangeFeedStartFrom.Beginning(),
ChangeFeedMode.Incremental);
while (iterator.HasMoreResults)
{
var changes = await iterator.ReadNextAsync();
foreach (var change in changes)
{
Console.WriteLine($"Detected change: {change.Id}");
// Processar a alteração (por exemplo, acionar evento, atualizar cache)
}
}
7. Utilização do Tempo de Vida (TTL) para Expiração Automática de Dados
Se você tem dados que são relevantes apenas por um tempo limitado, como logs ou dados de sessão, habilitar o Tempo de Vida (TTL) no Azure Cosmos DB pode ajudar a gerenciar os custos de armazenamento. O TTL deleta automaticamente os dados expirados após o período de retenção especificado, eliminando a necessidade de limpeza manual de dados. Essa abordagem não apenas reduz a quantidade de dados armazenados, mas também garante que seu banco de dados seja otimizado para eficiência de custos, removendo informações obsoletas ou desnecessárias.
Melhores Práticas
- Defina o TTL para containers onde os dados devem expirar automaticamente para reduzir os custos de armazenamento.
Exemplo: Configurando o Tempo de Vida (TTL) para Dados Expirados
{
"id": "sessionDataContainer",
"partitionKey": { "paths": ["/sessionId"] },
"defaultTtl": 3600 // 1 hour (3600 seconds)
}
No Cosmos DB, o valor máximo de Tempo-para-Viver (TTL) que pode ser definido é de 365 dias (1 ano). Isto significa que os dados podem ser automaticamente excluídos após expirarem dentro de um ano da criação ou última modificação, dependendo de como você configura o TTL.
8. Avoid Cross-Partition Queries
Consultas entre partições podem aumentar significativamente os RU/s e a latência. Para evitar isso:
Melhores Práticas
- Sempre inclua a chave de partição em suas consultas.
- Projete sua estratégia de partição para minimizar o acesso entre partições.
Exemplo: Consultando com a Chave de Partição para Evitar Consultas entre Partições
var query = new QueryDefinition("SELECT * FROM Orders o WHERE o.customerId = @customerId")
.WithParameter("@customerId", "12345");
var resultSetIterator = container.GetItemQueryIterator<Order>(query, requestOptions: new QueryRequestOptions
{
PartitionKey = new PartitionKey("12345")
});
while (resultSetIterator.HasMoreResults)
{
var response = await resultSetIterator.ReadNextAsync();
foreach (var order in response)
{
Console.WriteLine($"Order ID: {order.Id}");
}
}
Conclusão
Estas dicas são muito eficazes durante o desenvolvimento. Ao implementar uma estratégia eficaz de partição, personalizando políticas de indexação, otimizando consultas, ajustando níveis de consistência e selecionando os modelos apropriados de provisionamento de throughput, você pode melhorar significativamente o desempenho e a eficiência da implantação do seu Azure Cosmos DB. Estas otimizações não apenas aprimoram a escalabilidade, mas também ajudam a gerenciar custos, proporcionando uma experiência de banco de dados de alto desempenho.
Source:
https://dzone.com/articles/optimizing-performance-in-azure-cosmos-db