Pular para o conteúdo principal

Estratégias de escalonamento de banco de dados: leitura de réplicas, fragmentação e muito mais

Dimensione seu banco de dados com réplicas de leitura, fragmentação horizontal, pool de conexões e estratégias de cache. Abrange PostgreSQL, MySQL e serviços de banco de dados gerenciados.

E
ECOSIRE Research and Development Team
|16 de março de 20269 min de leitura1.7k Palavras|

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.

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 ANALYZE para 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ânciavCPUmemória RAMConexõesCusto Mensal (RDS)
db.t3.médio24 GB100US$ 65
db.r6g.large216 GB200US$ 175
db.r6g.xlarge432 GB400US$ 350
db.r6g.2xlarge864 GB800US$ 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&lt;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çãoDescriçãoMelhor para
Baseado em hashHash a chave de fragmento, distribua uniformementeDistribuição uniforme de dados
Baseado em intervaloAtribuir intervalos aos fragmentos (por exemplo, AM, NZ)Séries temporais, dados geográficos
Baseado em inquilinoUm fragmento por locatário/organizaçãoSaaS 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étricaFerramentaLimite de alerta
Latência de consulta (P95)pg_stat_statements>500ms
Conexões ativaspg_stat_atividade>80% do máximo
Proporção de acertos de cachepg_stat_database<95%
Atraso na replicaçãopg_stat_replicação>1 segundo
Inchaço de mesapg_stat_user_tables>20% de tuplas mortas
Espera de E/S de discoiostat/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.

E

Escrito por

ECOSIRE Team

Technical 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.