Quando estamos trabalhando com um banco de dados, a otimização é crucial e fundamental em termos de desempenho e eficiência da aplicação. Da mesma forma, no Azure Cosmos DB, a otimização é crucial para maximizar a eficiência, minimizar os custos e garantir que sua aplicação se expanda de forma eficaz. 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 Correta
A escolha de uma chave de partição apropriada é vital para bancos de dados distribuídos como o Cosmos DB. Uma boa chave de partição garante que os dados sejam distribuídos de forma equitativa 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 que 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 as operações de leitura e gravação de forma equitativa.
- Mantenha os dados relacionados juntos para minimizar consultas entre partições.
Exemplo: Criando um Contêiner com uma Chave de Partição Ideal
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. Correta Uso de Indexação
No Azure Cosmos DB, os índices são aplicados a todas as propriedades por padrão, o que pode ser benéfico, mas pode resultar em custos de armazenamento e RU/s aumentados. Para melhorar o desempenho da consulta e minimizar despesas, considere personalizar a política de indexação. Cosmos DB suporta três tipos de índices: Índices de Intervalo, Índices Espaciais e Índices Compostos. Use o tipo adequado sabiamente.
Boa Prática
- Exclua campos desnecessários da indexação.
- Use índices compostos para consultas com vários 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 os tipos de indexação aqui.
3. Otimizar Consultas
A consulta eficiente é crucial para minimizar as unidades de solicitação (RU/s) e melhorar o desempenho no Azure Cosmos DB. O custo de RU/s depende da complexidade e do tamanho da consulta.
O uso de executores em massa pode reduzir ainda mais os custos, diminuindo as RUs consumidas por operação. Essa otimização ajuda a gerenciar o uso de RUs de forma eficaz e reduz suas despesas gerais no 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 da partição em sua consulta.
- Use filtros em campos indexados para reduzir os custos de consulta.
Exemplo: Buscar Registro de 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 a garantias relacionadas à velocidade. Existem cinco níveis de consistência (Forte, Obsolescência Limitada, Sessão, Prefixo Consistente e Eventual) disponíveis em Cosmos DB. Cada nível de consistência impacta a latência, a disponibilidade e a taxa de transferência.
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 RU/s e latência.
Exemplo: Definindo Nível de Consistência
var cosmosClient = new CosmosClient(
"",
"",
new CosmosClientOptions
{
// Defina a consistência para "Sessão" para desempenho equilibrado
ConsistencyLevel = ConsistencyLevel.Session
});
Leia mais sobre o nível de consistência aqui.
5. Use o Throughput Provisionado (RU/s) e o Dimensionamento Automático com Sabedoria
A provisionamento de throughput é um fator-chave para alcançar eficiência de custos e desempenho ideal no Azure Cosmos DB. O serviço permite que você configure o throughput de duas maneiras:
- RU/s Fixo: Um nível constante de Unidades de Requisição por segundo (RU/s) predefinido, adequado para cargas de trabalho com demandas de desempenho consistentes.
- Dimensionamento Automático: Uma opção dinâmica que ajusta automaticamente o throughput com base nas flutuações de carga de trabalho, proporcionando 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 dimensionamento automático para cargas de trabalho imprevisíveis ou com picos.
Exemplo: Provisionando Throughput com Dimensionamento Automático
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 o 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, orientado por eventos, capturando automaticamente as alterações no banco de dados, eliminando a necessidade de polling. Isso reduz a sobrecarga de consulta e aprimora a eficiência.
Melhores Práticas
- Use o feed de alterações em cenários onde as alterações de dados em tempo real precisam ser processadas (por exemplo, análises em tempo real, notificações, alertas).
Exemplo: Lendo a partir 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 período 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. Esta 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 contêineres onde os dados devem expirar automaticamente para reduzir os custos de armazenamento.
Exemplo: Definindo 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 de Vida (TTL) que pode ser definido é de 365 dias (1 ano). Isso significa que os dados podem ser automaticamente excluídos após expirarem dentro de um ano após a criação ou última modificação, dependendo de como você configura o TTL.
8. Evite Consultas entre Partições
Consultas entre partições podem aumentar significativamente o RU/s e a latência. Para evitar isso:
Melhor Prática
- Inclua sempre 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 Consulta 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
Essas dicas são muito eficazes durante o desenvolvimento. Ao implementar uma estratégia de partição eficaz, personalizar políticas de indexação, otimizar consultas, ajustar níveis de consistência e selecionar os modelos de provisão de throughput apropriados, você pode melhorar muito o desempenho e a eficiência da sua implantação do Azure Cosmos DB. Essas otimizações não apenas aumentam a escalabilidade, mas também ajudam na gestão de custos enquanto proporcionam uma experiência de banco de dados de alto desempenho.
Source:
https://dzone.com/articles/optimizing-performance-in-azure-cosmos-db