🎯 ATIVIDADE 11 — O VELOCÍMETRO DOS DADOS
Bem-vindo à décima primeira semana (4 aulas) do curso de Banco de Dados. Até aqui, trabalhamos com tabelas pequenas, onde as consultas respondem instantaneamente. Mas o que acontece quando a tabela tem 10 milhões de linhas? Sem os índices corretos, seu banco travará e a aplicação ficará lenta. Hoje, você aprenderá a criar índices e a ler o plano de execução de uma consulta para atuar como um Especialista em Performance (Tuning). 🛡️⚡
🎯 Objetivo da Aula
Ao final desta semana, você será capaz de:
- Compreender a diferença entre busca sequencial (Sequential Scan) e busca por índice (Index Scan).
- Criar e gerenciar Índices B-Tree e Hash no PostgreSQL e MySQL.
- Interpretar o plano de execução de uma consulta usando o comando
EXPLAIN. - Identificar consultas lentas e propor a indexação correta para otimização de performance.
🏢 O Cenário Prático (Seu Desafio)
O aplicativo de rastreamento de entregas da TecProExpress está enfrentando lentidão crítica. O time de suporte identificou que a consulta de busca por CPF do cliente na hora de listar as entregas está levando mais de 5 segundos para responder no banco de produção.
Como Arquiteto de Banco de Dados, você recebeu a missão de analisar as consultas de busca utilizando ferramentas de execução e aplicar índices estratégicos para reduzir o tempo de busca para menos de 5 milissegundos.
🧠 Fundamentos: A Teoria Traduzida
Buscar dados em uma tabela sem índice é como procurar uma palavra em um dicionário que não está em ordem alfabética: você precisa ler o livro inteiro, página por página (Full Table Scan / Seq Scan). Criar um índice é como criar o índice remissivo no fim do livro: você vai direto para a página certa instantaneamente.
📊 Estrutura de Busca: B-Tree vs. Hash
flowchart TD
subgraph BTree ["Árvore B-Tree (Busca de Intervalos: >, <, >=, <=)"]
Root["Raiz: id = 50"] --> L1["Esquerda: < 50"]
Root --> R1["Direita: >= 50"]
L1 --> L2["Folha: 10, 20, 30"]
R1 --> R2["Folha: 50, 60, 70"]
end
- B-Tree (Padrão): Organiza os dados em uma árvore balanceada. Excelente para consultas de igualdade (
=) e buscas por intervalo (BETWEEN,>,<). - Hash: Mapeia chaves diretamente para endereços físicos. Perfeito para igualdades exatas (
=), mas inútil para intervalos.
📖 Exemplo Guiado: Usando o EXPLAIN
Vamos analisar como o banco de dados planeja fazer uma busca antes de criar o índice.
1. Inicializando o Banco de Dados
CREATE DATABASE tecpro_performance;
-- (Nota: No pgAdmin, abra a Query Tool apontando para o novo banco)
2. Criando Tabela e Analisando sem Índice
CREATE TABLE entrega (
id SERIAL PRIMARY KEY,
codigo_rastreamento VARCHAR(50),
data_envio DATE
);
-- Analisando a busca por código de rastreamento antes do índice
EXPLAIN ANALYZE
SELECT * FROM entrega WHERE codigo_rastreamento = 'TRK1002938';
Saída Esperada no pgAdmin (Console):
Seq Scan on entrega (cost=0.00..38.25 rows=1 width=58) (actual time=0.045..0.082 rows=0 loops=1)
(Nota: O termo Seq Scan indica que o banco leu a tabela inteira do início ao fim para tentar achar o registro).
🛠️ Prática Obrigatória 1: Análise e Indexação
- Crie a tabela
cliente_historicocom as colunas:id(PK),nome,cpf(sem chave única física inicial) eemail. - Popule a tabela com alguns registros fictícios.
- Execute o comando
EXPLAINpara analisar a busca porcpf:EXPLAIN SELECT * FROM cliente_historico WHERE cpf = '12345678901'; - Crie um índice B-Tree na coluna
cpfe execute novamente oEXPLAIN. Veja a diferença.
🛠️ Prática Obrigatória 2: B-Tree vs. Hash (Performance)
- Crie um índice do tipo Hash na coluna
emailda tabelacliente_historico. - Crie um índice do tipo B-Tree na coluna
id(gerado automaticamente pela PK). - Escreva o script SQL de criação dos dois índices (PostgreSQL e MySQL equivalentes).
📤 Instruções de Entrega (Microsoft Teams)
Após validar a performance das suas consultas locais:
- Salve o script SQL contendo a criação da tabela, comandos de
EXPLAINe a criação dos índices em um arquivo.sql(Ex:Atividade_11_SeuNome.sql). - Adicione comentários no código explicando o que significa o custo (
cost) retornado peloEXPLAINe quando se deve preferir um índice B-Tree sobre um Hash. - Envie o arquivo
.sqlno Microsoft Teams.
💡 Checkpoint de Lógica
[!IMPORTANT] O Preço do Índice: Se os índices deixam as consultas super rápidas, por que não indexamos todas as colunas de todas as tabelas? (Resposta: Cada índice consome espaço físico em disco e reduz a velocidade de escrita (
INSERT,UPDATE,DELETE), pois o banco de dados precisa atualizar os índices a cada modificação. O bom arquiteto indexa apenas colunas usadas frequentemente em filtrosWHEREe junçõesJOIN). 🧠🛡️
🔥 Desafio de Fixação (Opcional)
Nível: Especialista em Performance 🏆
O que é um Covering Index (ou Índice Composto)? Como você criaria um único índice para otimizar uma busca que filtra por cidade E por status ao mesmo tempo?
🔑 Gabarito de Código/Fórmulas Completo
🐘 Padrão PostgreSQL (pgAdmin)
-- 1. Criação da Tabela
CREATE TABLE cliente_historico (
id SERIAL PRIMARY KEY,
nome VARCHAR(100),
cpf VARCHAR(11),
email VARCHAR(100)
);
-- 2. Criação do Índice B-Tree (Foco em buscas por igualdade e ordenações)
CREATE INDEX idx_cli_cpf ON cliente_historico(cpf);
-- 3. Criação do Índice Hash (Exclusivo para igualdade exata)
CREATE INDEX idx_cli_email_hash ON cliente_historico USING HASH (email);
-- 4. Verificação de Execução
EXPLAIN ANALYZE
SELECT * FROM cliente_historico WHERE cpf = '12345678901';
🐬 Comparativo MySQL (Workbench)
-- No MySQL, o índice Hash não é suportado no motor padrão InnoDB (apenas B-Tree)
CREATE INDEX idx_cli_cpf ON cliente_historico(cpf);
CREATE INDEX idx_cli_email ON cliente_historico(email);
🔍 Explicação do Gabarito:
- idx_cli_cpf: Índice B-Tree criado para buscas por CPF.
- USING HASH: Sintaxe do PostgreSQL para criar índices usando hashing direto. Muito rápido para buscas exatas por e-mail, mas não suporta operadores como
>,<,LIKEouORDER BY. - EXPLAIN ANALYZE: Mostra o planejamento do otimizador e executa a query, trazendo o tempo real de CPU em milissegundos.