Um banco de dados que responde em segundos não é apenas questão de paciência, é custo de hardware, horas de desenvolvedor e experiência do usuário. A otimização de banco de dados é o processo de ajustar índices, consultas, configurações e hardware para reduzir tempo de resposta e consumo de recursos. Um checklist típico inclui: revisar índices ausentes ou duplicados, analisar planos de execução, ajustar buffers e cache, e monitorar gargalos de I/O.
Este checklist serve para bancos relacionais (MySQL, PostgreSQL, SQL Server, Oracle) e alguns NoSQL. Use-o quando perceber lentidão em relatórios, timeout em APIs ou crescimento de custo de nuvem sem aumento de tráfego.
Índices e Estrutura de Dados
Revise índices ausentes nas consultas mais frequentes
O banco de dados mantém estatísticas de uso. No MySQL, o performance_schema mostra quais consultas escaneiam tabelas inteiras. No SQL Server, o Database Engine Tuning Advisor sugere índices. Crie índices compostos que cubram colunas de WHERE, JOIN e ORDER BY.
Elimine índices duplicados ou subutilizados
Índices que nunca são usados consomem espaço em disco e tornam escritas mais lentas. Consulte sys.dm_db_index_usage_stats (SQL Server) ou pg_stat_user_indexes (PostgreSQL) para identificar índices com zero scans.
Considere índices parciais e filtrados
Em PostgreSQL, um índice parcial WHERE status = 'ativo' ocupa menos espaço e acelera consultas que filtram por esse estado. No SQL Server, índices filtrados funcionam de forma similar.
Ajuste a ordem das colunas em índices compostos
Coloque primeiro a coluna com maior seletividade (mais valores distintos). Um índice (sexo, cpf) é menos eficiente que (cpf, sexo), porque o banco pode pular a segunda coluna se a primeira já reduz bem o resultado.
Consultas SQL
Identifique consultas lentas com logs de slow query
Ative o slow_query_log no MySQL ou auto_explain no PostgreSQL. Defina long_query_time para 1 segundo. Analise uma amostra de 100 consultas lentas, elas costumam representar 80% do tempo de resposta.
Reescreva subconsultas como JOINs quando possível
Subconsultas correlacionadas executam uma vez para cada linha externa. Um SELECT * FROM pedidos WHERE cliente_id IN (SELECT id FROM clientes WHERE ativo = 1) pode ser reescrito como SELECT p.* FROM pedidos p JOIN clientes c ON p.cliente_id = c.id WHERE c.ativo = 1.
Evite SELECT * em produção
Buscar colunas desnecessárias aumenta I/O e tráfego de rede. Especifique apenas as colunas que a aplicação realmente usa. Em tabelas com mais de 50 colunas, o ganho é significativo.
Use LIMIT ou TOP para paginação real
OFFSET + LIMIT varre linhas descartadas. No PostgreSQL, use keyset pagination com WHERE id > ultimo_id ORDER BY id LIMIT 10. No SQL Server, OFFSET...FETCH NEXT com índice na coluna de ordenação.
Configuração do Servidor
Ajuste o buffer pool ou cache de dados
No MySQL/InnoDB, innodb_buffer_pool_size deve ocupar 70-80% da RAM disponível. No PostgreSQL, shared_buffers fica em 25% da RAM. Valores abaixo do ideal forçam leituras de disco.
Configure o tamanho de conexões corretamente
max_connections alto demais causa contenção de CPU e memória. Calcule: pico de usuários simultâneos × tempo médio de consulta (em segundos) / 60. Se o resultado ultrapassar 200, considere um pool de conexões como PgBouncer.
Habilite compressão de dados em tabelas grandes
Tabelas com mais de 10 GB se beneficiam de compressão. No PostgreSQL, o TOAST comprime automaticamente colunas largas. No SQL Server, compressão de página reduz I/O em 30-50% em tabelas com muitos dados repetidos.
Use particionamento de tabelas para manutenção
Particione por data ou chave natural. A exclusão de partições antigas é mais rápida que DELETE. Consultas com filtro na chave de partição escaneiam apenas a partição relevante.
Hardware e Armazenamento
Migre para SSDs NVMe se ainda usar HDDs
O tempo de busca cai de ~10 ms (HDD) para ~0,1 ms (NVMe). Bancos com workload de leitura aleatória, comuns em OLTP, ganham de 5 a 10x em throughput.
Separe dados, logs e temporários em volumes diferentes
Logs de transação (WAL no PostgreSQL, redo log no MySQL) competem por I/O com dados. Coloque cada um em disco próprio. No mínimo, separe logs de dados.
Monitore latência de I/O com ferramentas do SO
iostat -x 1 mostra await (tempo médio de resposta) e %util. Valores de await acima de 20 ms indicam saturação de disco. Considere aumentar o cache de gravação do controlador RAID (com bateria).
Monitoramento e Manutenção Contínua
Configure alertas para consultas lentas e deadlocks
Ferramentas como Prometheus + pg_stat_statements ou MySQL Enterprise Monitor disparam alertas quando o tempo médio de consulta sobe 50% acima da linha de base. Defina thresholds por ambiente (produção vs. staging).
Execute ANALYZE e VACUUM (PostgreSQL) ou OPTIMIZE (MySQL) regularmente
Estatísticas desatualizadas levam o otimizador a escolher planos ruins. No PostgreSQL, autovacuum deve rodar com autovacuum_vacuum_scale_factor = 0.01 para tabelas pequenas. No MySQL, innodb_stats_auto_recalc = ON ajuda.
Revise o crescimento de tamanho do banco semanalmente
Tabelas que crescem 10% por semana sem aumento de usuários indicam dados órfãos ou logs não truncados. Crie um script que compare o tamanho da semana anterior e alerte se a taxa ultrapassar 5%.
O Erro Mais Comum
O erro mais comum em otimização de banco de dados é pular a análise de consultas reais e sair ajustando configurações do servidor. Aumentar innodb_buffer_pool_size ou comprar mais RAM sem antes olhar os planos de execução é como colocar pneus novos num carro com o motor fundido. Sempre comece pelas consultas lentas, elas revelam exatamente onde o banco perde tempo.
Perguntas Frequentes
Qual a diferença entre otimização de banco de dados e tuning?
Otimização é o processo amplo de melhorar desempenho, incluindo índices, consultas e hardware. Tuning é a parte fina de ajustar parâmetros do servidor (buffers, cache, paralelismo). Na prática, tuning vem depois da otimização estrutural.
Com que frequência devo revisar o desempenho do banco?
Em ambientes de produção, revise semanalmente as consultas lentas e o crescimento de tamanho. A cada trimestre, refaça o checklist completo, incluindo índices e configurações. Após mudanças de schema ou versão do banco, execute imediatamente.
Preciso de ferramentas pagas para otimizar?
Não. PostgreSQL, MySQL e SQL Server oferecem views de desempenho gratuitas: pg_stat_statements, performance_schema, sys.dm_exec_query_stats. Ferramentas pagas como SolarWinds DPA ou New Relic simplificam a visualização, mas não substituem a análise de planos de execução.
O que causa a maioria das consultas lentas?
Falta de índices adequados responde por cerca de 70% dos casos. O restante divide-se entre estatísticas desatualizadas, joins sem índices, e consultas que retornam mais dados que o necessário.
Otimização de banco de dados resolve problemas de rede?
Não. Otimização atua no servidor de banco, não na latência de rede entre aplicação e banco. Se o problema for rede, use ping e traceroute para diagnosticar. Colocar banco e aplicação na mesma zona de nuvem reduz latência.
Vale a pena usar cache externo (Redis, Memcached) antes de otimizar?
Depende. Se 80% das consultas são repetitivas (dados de catálogo, sessões de usuário), um cache externo alivia o banco imediatamente. Mas não ignore a otimização das consultas que batem no banco, cache não resolve índices ausentes.


