Otimizando PostgreSQL para Aplicações .NET
Otimizando PostgreSQL para Aplicações .NET
Ao desenvolver aplicações de alta performance com .NET e PostgreSQL, a otimização do banco de dados pode ser a diferença entre um sistema fluído e um gargalo constante. Neste artigo, veremos boas práticas, ajustes no PostgreSQL e otimizações no lado .NET.
Por que PostgreSQL no .NET?
O PostgreSQL é um dos bancos de dados relacionais mais robustos e flexíveis. Com o driver Npgsql, integra-se nativamente ao .NET, oferecendo suporte a recursos avançados como JSONB, busca textual e particionamento.
Gargalos Comuns de Performance
- Índices mal otimizados.
- Excesso de conexões abertas/fechadas.
- Escritas em lotes grandes sem batch.
- Estatísticas desatualizadas levando a planos ruins.
Veja também: Hangfire e Filas Descentralizadas
Configuração do PostgreSQL para Alta Performance
Parâmetro | Ajuste Recomendado | Impacto |
---|---|---|
max_connections | Ajustar conforme limite do pool | Evita sobrecarga |
shared_buffers | 25-40% da RAM | Cache rápido |
work_mem | 4–64MB por query | Melhor sorting |
maintenance_work_mem | 256MB+ | Índices mais rápidos |
effective_cache_size | 50-75% da RAM | Melhor planejamento |
Exemplo: postgresql.conf
max_connections = 200
shared_buffers = 4GB
work_mem = 16MB
maintenance_work_mem = 512MB
effective_cache_size = 12GB
Boas Práticas de Modelagem no .NET
- Escolher tipos corretos (
uuid
,timestamp with time zone
). - Evitar
SELECT *
em produção. - Usar JSONB para partes flexíveis do schema.
- Particionar dados grandes por tempo ou chave.
Pool de Conexões no .NET
using Npgsql;
using System;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var connString = "Host=localhost;Username=appuser;Password=secret;Database=mydb;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50;Timeout=15";
await using var conn = new NpgsqlConnection(connString);
await conn.OpenAsync();
await using var cmd = new NpgsqlCommand("SELECT COUNT(*) FROM users", conn);
var count = await cmd.ExecuteScalarAsync();
Console.WriteLine($"Total de usuários: {count}");
}
}
Dicas:
- Ativar
Pooling=true
. - Ajustar
Minimum
eMaximum Pool Size
. - Monitorar
pg_stat_activity
.
Monitoramento e Métricas
Habilitar
pg_stat_statements
para queries lentas.Checar cache hit ratio:
SELECT sum(blks_hit) / sum(blks_hit + blks_read) AS cache_hit_ratio FROM pg_stat_database;
Integrar com Grafana + Prometheus.
Exemplo Completo: Bulk Insert Otimizado
using Npgsql;
using System;
using System.Threading.Tasks;
class BulkInsertExample
{
public static async Task Main()
{
var connString = "Host=localhost;Username=appuser;Password=secret;Database=mydb;Pooling=true";
await using var conn = new NpgsqlConnection(connString);
await conn.OpenAsync();
using var writer = conn.BeginBinaryImport("COPY products (id, name, price) FROM STDIN (FORMAT BINARY)");
for (int i = 0; i < 1000; i++)
{
writer.StartRow();
writer.Write(Guid.NewGuid(), NpgsqlTypes.NpgsqlDbType.Uuid);
writer.Write($"Produto {i}", NpgsqlTypes.NpgsqlDbType.Text);
writer.Write(i * 10.5m, NpgsqlTypes.NpgsqlDbType.Numeric);
}
await writer.CompleteAsync();
Console.WriteLine("Inserção em lote concluída.");
}
}
Links Internos
Referências Externas
Conecte-se comigo no LinkedIn e compartilhe suas dicas de otimização de PostgreSQL para .NET.