Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

⚡ CAPÍTULO 16: VIEWS, ÍNDICES E OTIMIZAÇÃO

Escrever um SQL que devolve o resultado correto é fácil. Escrever um SQL que devolve o resultado correto em 3 milissegundos sob um banco com 10 milhões de linhas é o que separa um programador iniciante de um Arquiteto de Software. 🛡️🧩


🎯 Objetivo Curricular

Aprender a abstrair a complexidade e aumentar a segurança com a criação de VIEWs. Entender o impacto arquitetural da criação de Índices na leitura vs gravação e analisar planos de execução com o comando EXPLAIN.


🏢 O Cenário Prático (Seu Desafio)

Na TecProExpress, a tabela de Pacotes atingiu 5 milhões de registros. A busca no painel do usuário ("Procurar pacote pelo Código de Rastreio") começou a demorar 8 segundos para responder. Os clientes estão reclamando no Reclame Aqui. Além disso, o RH pediu um relatório com os dados dos estagiários, mas o banco se recusou a dar acesso à tabela original, pois nela constam salários confidenciais.

"Seu desafio é criar uma VIEW cega para proteger os salários do RH e implementar um Índice (Index) no Código de Rastreio para derrubar o tempo de busca da tabela de pacotes de 8 segundos para 3 milissegundos!"


🧠 Fundamentos 1: O Encapsulamento (VIEW)

Uma VIEW (Visão) é uma tabela virtual. Ela não armazena dados físicos no HD. Ela armazena apenas a "lógica" de um SELECT.

  • Segurança: Você pode criar uma VIEW que esconde a coluna "Salario" da tabela original e dar permissão para o usuário ler apenas essa VIEW.
  • Abstração: Se você tem um relatório que exige 5 JOINs super complexos, você pode salvar tudo isso em uma VIEW. O desenvolvedor frontend apenas fará SELECT * FROM nome_da_view;.

🛠️ Criando a Visão do RH

-- DDL Rápido: A tabela original (Intocável)
-- CREATE TABLE funcionario (id INT, nome VARCHAR(50), salario DECIMAL(10,2));

-- Criando a Visão Segura (Ignoramos o salário de propósito)
CREATE VIEW vw_funcionarios_rh AS
SELECT id, nome FROM funcionario;

-- Como o usuário (RH) irá consultar:
SELECT * FROM vw_funcionarios_rh;

🧠 Fundamentos 2: O Acelerador (Índices)

Quando você manda o SGBD procurar o código de rastreio 'BR123', e a tabela não tem Índice, o banco faz um Full Table Scan (Ele lê a linha 1, depois a linha 2... até a linha 5.000.000). Isso é terrível.

Um Índice (Index) é uma cópia organizada de uma coluna específica, guardada em uma árvore de busca (B-Tree). Funciona como o índice remissivo no final de um livro.

📊 Comparação de Busca

flowchart LR
    A["Tabela sem Índice<br/>(Lê 5 milhões de linhas)"] -->|O(N)| B["Demora 8 segundos"]
    C["Tabela com Índice B-Tree<br/>(Busca binária)"] -->|O(log N)| D["Demora 3 milissegundos"]

⚠️ O Preço do Índice

Se índices são tão maravilhosos, por que não colocamos em TODAS as colunas? Porque o Índice atrasa a gravação. Toda vez que houver um INSERT ou UPDATE, o banco terá que escrever o dado na tabela e depois reorganizar a árvore do Índice.

A Regra: Tabelas com muita leitura (Consultas) exigem índices. Tabelas com muita gravação (ex: Logs de GPS em tempo real) exigem o mínimo de índices possível.


📖 Exemplo Guiado: Otimizando o Rastreio (EXPLAIN)

O comando EXPLAIN é a ferramenta de raio-x do SGBD. Ele não executa a consulta, ele te diz o "Plano Matemático" que o SGBD faria.

🛠️ Código do Exemplo

-- DDL Base
-- CREATE TABLE pacote_log (id INT, codigo_rastreio VARCHAR(15), status VARCHAR(20));
-- (Imagine 5 milhões de inserts aqui)

-- 1. O Diagnóstico: "Como você faria essa busca, Banco de Dados?"
EXPLAIN SELECT * FROM pacote_log WHERE codigo_rastreio = 'BR123';
-- O SGBD responderá: type = "ALL" (Ele vai ler TODAS as linhas).

-- 2. A Cura (DDL de Otimização)
CREATE INDEX idx_pacote_rastreio ON pacote_log(codigo_rastreio);

-- 3. O Novo Diagnóstico
EXPLAIN SELECT * FROM pacote_log WHERE codigo_rastreio = 'BR123';
-- O SGBD responderá: type = "ref" (Usando o Índice). Velocidade máxima atingida!

🛠️ Prática Obrigatória: Abstração e Velocidade

Cenário: O sistema de relatórios da TecProExpress.

  1. Crie a tabela faturamento com id_venda, data_venda, nome_cliente e valor_lucro.
  2. Crie uma VIEW chamada vw_vendas_publicas que mostre apenas a data e o cliente (escondendo o lucro da equipe de vendas).
  3. Crie um INDEX na coluna data_venda para acelerar os relatórios de fechamento mensal.

🚀 Script de Seed (Gabarito de Otimização)

-- 1. Tabela Original (DDL)
CREATE TABLE faturamento (
    id_venda INT PRIMARY KEY,
    data_venda DATE,
    nome_cliente VARCHAR(100),
    valor_lucro DECIMAL(15,2)
);

-- 2. View Segura (DQL encapsulada em DDL)
CREATE VIEW vw_vendas_publicas AS
SELECT data_venda, nome_cliente 
FROM faturamento;

-- 3. Índice Estratégico (DDL)
CREATE INDEX idx_data_fechamento ON faturamento(data_venda);

📤 Instruções de Entrega (Microsoft Teams)

Após validar seus códigos práticos e de estudo:

Use o operador e para critérios rigorosos e ou para critérios flexíveis. Salve os arquivos com a extensão .sql (Ex: Atividade_XX_SeuNome.sql ou Atividade_XX_SeuNome.png ou Atividade_XX_SeuNome.drawio


💡 Checkpoint de Lógica

[!TIP] Dica do Engenheiro: Um erro clássico de performance é colocar o código dentro de funções (ex: WHERE YEAR(data_venda) = 2026). Quando você envolve a coluna com uma função, o SGBD é forçado a ignorar o Índice e fazer o Full Table Scan. O correto para alta velocidade é: WHERE data_venda BETWEEN '2026-01-01' AND '2026-12-31'. 🧠🛡️