Estratégias de escalonamento de banco de dados: leitura de réplicas, fragmentação e muito mais
O desempenho do banco de dados é o gargalo em 78% dos problemas de dimensionamento de aplicativos Web. Os aplicativos podem ser dimensionados horizontalmente com esforço mínimo, mas os bancos de dados resistem ao dimensionamento horizontal. As estratégias escolhidas para o dimensionamento do banco de dados determinam se seu aplicativo atende 100 usuários ou 100.000 usuários com desempenho aceitável.
Este guia cobre o espectro completo de estratégias de escalonamento de banco de dados, desde otimizações simples que atrasam a necessidade de escalonamento até técnicas avançadas, como fragmentação horizontal.
Principais conclusões
- Otimize consultas e adicione índices antes de adicionar infraestrutura --- isso resolve 60% dos problemas de desempenho do banco de dados
- As réplicas de leitura são a estratégia de escalonamento de menor risco e lidam com 80% das cargas de trabalho com uso intenso de leitura
- O pool de conexões é obrigatório quando seu aplicativo executa mais de 10 instâncias
- A fragmentação horizontal é um último recurso que introduz uma complexidade significativa de aplicação
A escada de escala
Dimensione nesta ordem. Cada etapa é mais barata e menos arriscada que a seguinte:
Etapa 1: Otimização de consulta (gratuita)
Antes de adicionar infraestrutura, certifique-se de que seu banco de dados existente esteja funcionando de maneira ideal.
-- Find slow queries in PostgreSQL
SELECT
calls,
mean_exec_time::numeric(10,2) AS avg_ms,
total_exec_time::numeric(10,2) AS total_ms,
query
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 20;
Otimizações comuns:
- Adicione índices ausentes para colunas filtradas com frequência
- Substitua
SELECT *por listas de colunas específicas - Use
EXPLAIN ANALYZEpara identificar varreduras sequenciais em tabelas grandes - Adicionar índices compostos para cláusulas WHERE de várias colunas
- Implementar paginação com paginação de conjunto de chaves em vez de
OFFSET
-- Bad: OFFSET pagination (scans all skipped rows)
SELECT * FROM orders ORDER BY created_at DESC LIMIT 20 OFFSET 10000;
-- Good: Keyset pagination (index-only scan)
SELECT * FROM orders
WHERE created_at < '2026-03-15T10:00:00Z'
ORDER BY created_at DESC
LIMIT 20;
Etapa 2: Escala vertical ($)
Aumente a CPU, a RAM e o armazenamento no seu servidor de banco de dados existente. Isso ganha tempo e não requer nenhuma alteração no aplicativo.
| Tamanho da instância | vCPU | memória RAM | Conexões | Custo Mensal (RDS) |
|---|---|---|---|---|
| db.t3.médio | 2 | 4 GB | 100 | US$ 65 |
| db.r6g.large | 2 | 16 GB | 200 | US$ 175 |
| db.r6g.xlarge | 4 | 32 GB | 400 | US$ 350 |
| db.r6g.2xlarge | 8 | 64 GB | 800 | US$ 700 |
A maioria dos aplicativos atinge seu limite de 64 GB de RAM e 8 vCPUs. Além disso, a escala vertical torna-se proibitiva em termos de custos.
Etapa 3: Pool de conexões ($)
Application (50 pods x 20 connections = 1,000 connections)
|
v
PgBouncer (25 database connections, transaction pooling)
|
v
PostgreSQL (25 active connections, manageable)
Configuração do PgBouncer:
[databases]
app = host=db.example.com port=5432 dbname=production
[pgbouncer]
listen_port = 6432
listen_addr = 0.0.0.0
auth_type = md5
pool_mode = transaction
default_pool_size = 25
max_client_conn = 1000
min_pool_size = 5
reserve_pool_size = 5
reserve_pool_timeout = 3
Etapa 4: Ler réplicas ($$)
As réplicas de leitura lidam com consultas SELECT, descarregando de 60 a 90% da carga do banco de dados do primário.
Arquitetura:
Write queries --> Primary database
|
Replication (async)
|
+----+----+
| |
Read queries --> Replica 1 Replica 2
Roteamento em nível de aplicativo (exemplo Drizzle ORM):
import { drizzle } from 'drizzle-orm/node-postgres';
import { Pool } from 'pg';
const primaryPool = new Pool({ connectionString: process.env.DATABASE_URL });
const replicaPool = new Pool({ connectionString: process.env.DATABASE_REPLICA_URL });
export const primaryDb = drizzle(primaryPool);
export const replicaDb = drizzle(replicaPool);
// In service code:
// Write operations use primaryDb
async createOrder(data: OrderInput) {
return primaryDb.insert(orders).values(data).returning();
}
// Read operations use replicaDb
async getOrders(organizationId: string) {
return replicaDb.select().from(orders)
.where(eq(orders.organizationId, organizationId))
.orderBy(desc(orders.createdAt));
}
Considerações sobre atraso de replicação: a replicação assíncrona introduz um atraso (normalmente de 10 a 100 ms). Imediatamente após uma gravação, a leitura da réplica pode retornar dados obsoletos. Use o primário para leituras que seguem gravações no mesmo fluxo de usuário.
Etapa 5: Cache ($$)
O cache do Redis elimina totalmente as consultas repetidas ao banco de dados.
async getProduct(id: string): Promise<Product> {
const cacheKey = `product:${id}`;
// Check cache first
const cached = await this.redis.get(cacheKey);
if (cached) return JSON.parse(cached);
// Cache miss: query database
const product = await this.db.select().from(products)
.where(eq(products.id, id))
.limit(1);
// Cache for 5 minutes
await this.redis.setex(cacheKey, 300, JSON.stringify(product[0]));
return product[0];
}
Estratégia de invalidação de cache: invalidar na gravação. Quando um produto for atualizado, exclua a chave de cache. Use um padrão de cache-aside (o aplicativo gerencia o cache) em vez de write-through (o banco de dados gerencia o cache).
Etapa 6: Fragmentação horizontal ($$$)
A fragmentação distribui dados entre várias instâncias de banco de dados com base em uma chave de fragmento.
| Estratégia de fragmentação | Descrição | Melhor para |
|---|---|---|
| Baseado em hash | Hash a chave de fragmento, distribua uniformemente | Distribuição uniforme de dados |
| Baseado em intervalo | Atribuir intervalos aos fragmentos (por exemplo, AM, NZ) | Séries temporais, dados geográficos |
| Baseado em inquilino | Um fragmento por locatário/organização | SaaS multilocatário |
Quando fragmentar:
- Banco de dados único excede 1 TB e está crescendo
- A taxa de transferência de gravação excede o que um único primário pode suportar
- Os custos de escala vertical excedem US$ 2.000/mês sem margem de manobra
Quando NÃO fragmentar:
- Você não esgotou as etapas 1 a 5
- Seus dados cabem em um único banco de dados de 500 GB
- Consultas entre fragmentos são comuns em seu aplicativo
Otimizações específicas do PostgreSQL
Particionamento (antes da fragmentação)
O particionamento de tabelas do PostgreSQL divide tabelas grandes em tabelas físicas menores, mantendo uma única tabela lógica:
-- Partition orders by month
CREATE TABLE orders (
id UUID PRIMARY KEY,
organization_id UUID NOT NULL,
created_at TIMESTAMP NOT NULL,
total DECIMAL(10,2)
) PARTITION BY RANGE (created_at);
CREATE TABLE orders_2026_01 PARTITION OF orders
FOR VALUES FROM ('2026-01-01') TO ('2026-02-01');
CREATE TABLE orders_2026_02 PARTITION OF orders
FOR VALUES FROM ('2026-02-01') TO ('2026-03-01');
CREATE TABLE orders_2026_03 PARTITION OF orders
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');
O particionamento melhora o desempenho de consultas de intervalo de tempo em 10 a 100x em tabelas grandes porque o PostgreSQL verifica apenas partições relevantes.
Aspiração e Manutenção
-- Check table bloat
SELECT
schemaname,
relname,
n_live_tup,
n_dead_tup,
round(n_dead_tup::numeric / greatest(n_live_tup, 1) * 100, 2) AS dead_pct
FROM pg_stat_user_tables
WHERE n_dead_tup > 1000
ORDER BY n_dead_tup DESC;
Configure o autovacuum agressivamente para tabelas com alta gravação:
ALTER TABLE orders SET (
autovacuum_vacuum_threshold = 100,
autovacuum_vacuum_scale_factor = 0.05,
autovacuum_analyze_threshold = 50,
autovacuum_analyze_scale_factor = 0.02
);
Monitorando o desempenho do banco de dados
Acompanhe essas métricas para entender quando e como escalar:
| Métrica | Ferramenta | Limite de alerta |
|---|---|---|
| Latência de consulta (P95) | pg_stat_statements | >500ms |
| Conexões ativas | pg_stat_atividade | >80% do máximo |
| Proporção de acertos de cache | pg_stat_database | <95% |
| Atraso na replicação | pg_stat_replicação | >1 segundo |
| Inchaço de mesa | pg_stat_user_tables | >20% de tuplas mortas |
| Espera de E/S de disco | iostat/CloudWatch | >20ms |
Uma taxa de acertos de cache abaixo de 95% é o indicador mais forte de que você precisa de mais memória. Aumentar shared_buffers e effective_cache_size costuma ser mais barato e rápido do que adicionar réplicas de leitura.
Acompanhamento de desempenho de consulta
-- Enable pg_stat_statements (postgresql.conf)
-- shared_preload_libraries = 'pg_stat_statements'
-- Find the top 10 most time-consuming queries
SELECT
queryid,
calls,
mean_exec_time::numeric(10,2) AS avg_ms,
total_exec_time::numeric(10,2) AS total_ms,
rows,
query
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
Revise as 10 principais consultas semanalmente. Otimizar até mesmo uma única consulta executada com frequência pode reduzir a carga geral do banco de dados em 10 a 30%.
Perguntas frequentes
Como sabemos quando é hora de escalar?
Monitore três métricas: latência de consulta P95 (alerta em 500ms), utilização de conexão (alerta em 80%) e utilização de CPU (alerta em 70% sustentado). Se você atinge esses limites regularmente, passe para o próximo degrau na escada de escala. Não pré-otimize --- dimensione quando os dados solicitarem.
Ler réplicas ou cache --- qual primeiro?
Comece com o cache. O cache Redis é mais simples de implementar, elimina mais carga (as ocorrências de cache ignoram totalmente o banco de dados) e custa menos. Adicione réplicas de leitura quando a taxa de acertos do cache já estiver acima de 80%, mas o banco de dados primário ainda estiver sob pressão por falhas de cache e operações de gravação.
Como funciona o escalonamento de banco de dados com Odoo?
Odoo usa exclusivamente PostgreSQL. Comece com a otimização de consultas (Odoo gera consultas complexas para relatórios). Adicione PgBouncer para pool de conexões quando você exceder 50 usuários simultâneos. Use réplicas de leitura para consultas de relatórios (configure a opção --db-replica do Odoo). ECOSIRE fornece otimização de desempenho Odoo incluindo ajuste de banco de dados.
O banco de dados gerenciado (RDS/Cloud SQL) vale o prêmio?
Sim, para a maioria das empresas. Os bancos de dados gerenciados lidam com backups, patches, failover e monitoramento automatizados. O custo adicional de 30-40% em relação ao PostgreSQL autogerenciado é compensado pelo tempo de engenharia que você economiza. A exceção são as implantações em larga escala, nas quais o custo adicional de uma instância grande excede o custo de um DBA de meio período.
O que vem a seguir
O dimensionamento de banco de dados é um componente de uma estratégia mais ampla de dimensionamento de infraestrutura. Combine-o com otimização de CDN para ativos estáticos, escalonamento automático do Kubernetes para pods de aplicativos e teste de carga para validar suas decisões de escalonamento em condições realistas.
Entre em contato com a ECOSIRE para obter consultoria de otimização de banco de dados ou consulte nosso guia DevOps para obter o roteiro completo de infraestrutura.
Publicado pela ECOSIRE – ajudando as empresas a dimensionar a infraestrutura de dados com confiança.
Escrito por
ECOSIRE TeamTechnical Writing
The ECOSIRE technical writing team covers Odoo ERP, Shopify eCommerce, AI agents, Power BI analytics, GoHighLevel automation, and enterprise software best practices. Our guides help businesses make informed technology decisions.
ECOSIRE
Expanda o seu negócio com ECOSIRE
Soluções empresariais em ERP, comércio eletrônico, IA, análise e automação.
Artigos Relacionados
Migrações de banco de dados com tempo de inatividade zero com Drizzle ORM
Execute migrações de banco de dados sem tempo de inatividade usando Drizzle ORM. Abrange padrão de contrato de expansão, alterações de esquema compatíveis com versões anteriores, estratégias de reversão e integração de CI/CD para PostgreSQL.
Regue ORM com PostgreSQL: guia completo
Guia completo para Drizzle ORM com PostgreSQL: design de esquema, migrações, consultas de tipo seguro, relações, transações e padrões de produção para aplicativos TypeScript.
ERP para empresas de tecnologia e SaaS: operações em escala
Guia completo de ERP para empresas de tecnologia e SaaS: gerenciamento de receita de assinaturas, crescimento de pessoal, aquisição de fornecedores e relatórios financeiros em grande escala.