Prévia do material em texto
Implemente práticas avançadas de SQL com disciplina e propósito. Comece projetando esquemas relacionais claros: normalize até o ponto em que a manutenção e as consultas se tornem previsíveis, depois denormalize onde a velocidade de leitura for crítica. Use chaves candidatas e índices com intenção — não crie índices por impulso. Analise cargas de trabalho e defina estratégias separadas para OLTP (transações rápidas, índices enxutos, integridade referencial rigorosa) e OLAP (consultas analíticas, partições e agregações pré-calculadas). Utilize Common Table Expressions (CTEs) para estruturar consultas complexas e torne o código legível; prefira CTEs nomeadas para dividir lógica em blocos. Quando necessário, empregue CTEs recursivos para hierarquias, mas controle profundidade e monitore desempenho. Adote window functions para cálculos que atravessam linhas sem agrupar — rank(), row_number(), lead()/lag() e sum() over() reduzem subconsultas e melhoram clareza. Prefira lateral joins (ou APPLY) quando precisar referenciar colunas da consulta externa em subconsultas que retornam múltiplas linhas por linha base. Otimize consultas com base em planos de execução: solicite EXPLAIN/EXPLAIN ANALYZE, leia custos estimados e reais, identifique varreduras completas (table scans) e substitua por seeks quando possível. Atualize estatísticas com frequência em tabelas voláteis; estatísticas desatualizadas produzem planos ruins. Combata parameter sniffing definindo recompile quando necessário, usando hints pontuais ou ajuste de parâmetros da sessão. Avalie cardinalidade e selecione índices cobridores (covering indexes) que incluam colunas utilizadas em SELECT para evitar lookups. Projete índices compostos com ordem lógica: coloque primeiro a coluna com maior seletividade e agrupe colunas usadas em filtros e junções. Use índices filtrados/particionados para reduzir manutenção e melhorar busca em subconjuntos. Particione grandes tabelas por intervalo ou lista conforme padrão temporal ou lógico; isso facilita manutenção, arquivamento e prune de partições em execuções de consulta. Para cargas massivas, prefira bulk inserts em janelas controladas e desative índices temporariamente quando a reconstrução for mais eficiente. Controle a concorrência definindo níveis de isolamento adequados: read committed é padrão em muitos SGDBs, mas em cenários de alta contenção avalie snapshot isolation ou serializable com cautela por custos de armazenamento e latência. Programe transações curtas: abra o menor escopo possível, confirme (COMMIT) cedo, evite bloqueios longos. Monitore deadlocks e implemente retry logic idempotente nas camadas de aplicação para resiliência. Proteja dados e consultas: sempre use queries parametrizadas para prevenir SQL injection; restrinja privilégios por princípio de menor privilégio; audite acessos sensíveis. Para dados semi-estruturados, aproveite tipos JSON/XML nativos e indexação específica (JSON indexes, GIN/GiST), mas mantenha modelagem relacional quando desempenho e consistência forem essenciais. Implemente camadas de abstração com procedures, funções e views quando reutilização e consistência forem necessárias, mas não abuse de abstrações que ocultem custos de I/O. Prefira procedures para lógica transacional colocada perto dos dados e funções para transformações determinísticas; documente contratos e efeitos colaterais (side effects). Use materialized views para pré-aggregação em cenários analíticos; programe refresh incremental quando o SGDB suportar, e avalie armazenamento vs. tempo de recomputação. Monitore e colete métricas: latência por query, throughput, taxa de cache hit, waits por tipo, uso de CPU e I/O. Configure alertas para degradação e use histórico de planos para detectar regressões após deploys. Estabeleça testes de performance automatizados que simulem cargas reais antes de mudanças estruturais. Adote práticas de versionamento de schema e migrações transacionais: escreva scripts idempotentes, teste rollback e garanta compatibilidade retroativa sempre que possível. Para integrações ETL/ELT, prefira mover dados brutos e transformar no destino (ELT) quando o data warehouse suportar forte processamento em coluna; otimize consultas analíticas com colunas comprimidas e formatos de armazenamento em colunas. Conclua adotando uma mentalidade de melhoria contínua: revise periodicamente índices, estatísticas e planos; documente decisões de modelagem e trade-offs de performance; treine equipes em leitura de planos e boas práticas de escrita de SQL. Ao combinar disciplina de engenharia, ferramentas de observabilidade e técnicas avançadas de SQL, transforme bancos de dados em ativos previsíveis, seguros e capazes de escalar com eficiência. PERGUNTAS E RESPOSTAS: 1) O que são window functions e quando usá-las? R: São funções que operam sobre um conjunto de linhas relacionadas à linha atual (ex.: row_number, sum over). Use para rankings, agregações por janela e cálculos sem agrupar. 2) Quando preferir partição a índice? R: Partição ajuda em manutenção e prune de grandes volumes por faixa lógica (datas). Índice otimiza acesso; use ambos conforme padrão de consulta e manutenção. 3) Como evitar SQL injection em queries complexas? R: Use sempre parametrização, prepared statements ou ORM seguros; evite concatenar strings; valide e sanitize entradas. 4) O que é parameter sniffing e sua mitigação? R: É quando o SGDB compila plano baseado em parâmetros específicos, às vezes ruim para outros valores. Mitigue com recompilações, hints, ou planos por opção. 5) Quando usar materialized views? R: Use para pré-calcular agregações e diminuir CPU/IO em consultas analíticas frequentes; avalie custo de refresh versus ganho em leitura. 3) Como evitar SQL injection em queries complexas? R: Use sempre parametrização, prepared statements ou ORM seguros; evite concatenar strings; valide e sanitize entradas. 4) O que é parameter sniffing e sua mitigação? R: É quando o SGDB compila plano baseado em parâmetros específicos, às vezes ruim para outros valores. Mitigue com recompilações, hints, ou planos por opção. 5) Quando usar materialized views? R: Use para pré-calcular agregações e diminuir CPU/IO em consultas analíticas frequentes; avalie custo de refresh versus ganho em leitura.