SQL
Indexes
Performance
Tuning
Postgres
MySQL
Query Optimization

Otimização de Bancos de Dados SQL: Índices, Particionamento e Tuning

Otimização de Bancos de Dados SQL: Índices, Particionamento e Tuning

Bancos de dados relacionais são o coração de muitas aplicações. Quando as consultas começam a ficar lentas, a experiência do usuário sofre e os custos de infraestrutura aumentam. Este artigo apresenta técnicas práticas para otimizar consultas e estrutura de dados.

1. Entendendo o Plano de Execução

A primeira coisa a fazer é analisar EXPLAIN (PostgreSQL) ou EXPLAIN ANALYZE (MySQL). Ele mostra como o otimizador planeja acessar os dados.

  • Seq Scan indica leitura completa da tabela, geralmente sinal de falta de índice.
  • Index Scan mostra que um índice está sendo usado.
  • Bitmap Index Scan combina múltiplos índices.
  • Nested Loop, Hash Join, Merge Join, escolha de algoritmo de join impacta performance.

Checklist de Análise

  • O plano usa índices adequados?
  • Quantas linhas são estimadas vs. reais?
  • Sort ou Hash Aggregate custosos?
  • O custo total está dentro do esperado?

2. Estratégias de Indexação

Índices B-Tree (padrão)

  • Ideais para buscas de igualdade e intervalos.
  • Crie índices nas colunas usadas em WHERE, JOIN, ORDER BY.

Índices Parciais

CREATE INDEX idx_orders_status_pending ON orders (status) WHERE status = 'pending';

Reduz o tamanho do índice ao focar apenas em linhas relevantes.

Índices Compostos

Ordene as colunas no índice na mesma ordem que aparecem nas cláusulas WHERE e ORDER BY.

CREATE INDEX idx_sales_date_customer ON sales (sale_date, customer_id);

Índices GIN/GIST (PostgreSQL)

  • Úteis para colunas JSONB, arrays, full-text search.
  • Exemplo: CREATE INDEX idx_data_json ON events USING GIN (data);

3. Particionamento de Tabelas

Dividir tabelas grandes em partições menores melhora leitura e manutenção.

  • Range Partitioning, por data (ex.: orders_2025_q1).
  • List Partitioning, por enumeração (ex.: status = 'completed').
  • Hash Partitioning, distribuição uniforme.

Exemplo de Range Partition (PostgreSQL)

CREATE TABLE orders ( id UUID PRIMARY KEY, order_date DATE NOT NULL, status TEXT NOT NULL, total NUMERIC ) PARTITION BY RANGE (order_date); CREATE TABLE orders_2025_q1 PARTITION OF orders FOR VALUES FROM ('2025-01-01') TO ('2025-04-01');

4. Normalização vs. Desnormalização

  • Normalização reduz redundância, facilita manutenção.
  • Desnormalização pode melhorar leitura ao evitar joins complexos.
  • Avalie trade-offs: se a maioria das consultas são read-heavy, considere tabelas de leitura otimizadas.

5. Configurações de Servidor

  • shared_buffers (PostgreSQL), 25% da RAM.
  • work_mem, memória por operação de sort/join.
  • innodb_buffer_pool_size (MySQL), 70-80% da RAM.
  • max_connections, ajuste conforme carga.

6. Monitoramento Contínuo

  • Use pg_stat_statements (PostgreSQL) ou performance_schema (MySQL) para identificar queries lentas.
  • Configure alertas de slow query log.
  • Ferramentas como pgBadger, Percona Toolkit ajudam a analisar logs.

7. Checklist de Otimização

  • Analisar planos de execução das queries críticas.
  • Criar índices adequados (B-Tree, parciais, compostos).
  • Avaliar necessidade de particionamento.
  • Revisar configuração de memória do servidor.
  • Monitorar e registrar queries lentas.
  • Revisar modelo de dados (normalização vs. desnormalização).

Conclusão

A otimização de bancos de dados não é um evento único, é um processo iterativo. Comece analisando os gargalos, aplique indexação inteligente, ajuste a configuração do servidor e monitore continuamente. Com essas práticas, você reduz latência, economiza recursos e oferece uma experiência mais fluida aos usuários.


Quais desafios de performance você encontrou em seus bancos de dados? Compartilhe nos comentários!

Leia também

Otimização de Bancos de Dados SQL: Índices, Particionamento e Tuning | Matheus Breguêz