Visualizações e Índices
Visualizações e Índices
Imagine que você pega livros frequentemente na biblioteca. Existem duas maneiras de encontrar um livro: a primeira é procurar em todas as prateleiras toda vez (varredura completa da tabela); a segunda é verificar primeiro o catálogo de índice e ir diretamente à prateleira correta (consulta por índice). A "lista de leitura recomendada" da biblioteca é como uma visualização — não é uma prateleira real, mas uma lista curada de livros de diferentes prateleiras, facilitando encontrar o que você quer. Visualizações e índices no SQL funcionam da mesma forma.
1. Conceitos Fundamentais
Visualização — Conceito
Uma visualização é uma tabela virtual que não armazena dados, mas salva uma instrução SELECT. Cada vez que você acessa a visualização, o banco de dados executa a consulta definida da visualização e retorna os resultados.
-- Criar uma visualização: visualização de informações de funcionários
CREATE VIEW v_employee_info AS
SELECT
e.employee_id,
CONCAT(e.first_name, e.last_name) AS nome,
e.salary,
d.department_name AS departamento,
d.city
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id;
Usar uma visualização é igual a usar uma tabela regular:
-- Consultar a visualização
SELECT * FROM v_employee_info WHERE salary > 10000;
Criando Visualizações
CREATE VIEW nome_visualizacao AS
SELECT instrucao;
-- Criar uma visualização de estatísticas de departamento
CREATE VIEW v_department_stats AS
SELECT
d.department_id,
d.department_name AS departamento,
COUNT(e.employee_id) AS qtd_funcionarios,
AVG(e.salary) AS salario_medio,
SUM(e.salary) AS salario_total
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id
GROUP BY d.department_id, d.department_name;
Modificando Visualizações
-- Método 1: CREATE OR REPLACE (recomendado)
CREATE OR REPLACE VIEW v_employee_info AS
SELECT
e.employee_id,
CONCAT(e.first_name, e.last_name) AS nome,
e.salary,
e.hire_date,
d.department_name AS departamento
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id;
-- Método 2: ALTER VIEW
ALTER VIEW v_employee_info AS
SELECT employee_id, first_name, last_name, salary FROM employees;
Excluindo Visualizações
DROP VIEW IF EXISTS v_employee_info;
Vantagens das Visualizações
| Vantagem | Descrição |
|---|---|
| Simplificar consultas complexas | Encapsula JOINs complexos como visualizações; use com apenas SELECT * FROM nome_visualizacao |
| Segurança de dados | Expõe apenas certas colunas ou linhas aos usuários, ocultando dados sensíveis |
| Independência lógica | Modificar definições de visualização não afeta aplicações que usam a visualização |
| Lógica consistente | Garante que todos os usuários usem a mesma lógica de consulta, evitando escrita repetida |
Desvantagens das Visualizações
| Desvantagem | Descrição |
|---|---|
| Sobrecarga de desempenho | Cada acesso requer executar a consulta subjacente; visualizações complexas podem ser lentas |
| Limitações de atualização | Visualizações contendo JOINs, funções de agregação ou DISTINCT geralmente não são atualizáveis |
| Dificuldade de depuração | Visualizações aninhadas em múltiplas camadas aumentam a dificuldade de solução de problemas |
Índice — Conceito
Um índice é uma estrutura de dados, semelhante ao sumário de um livro, que ajuda o banco de dados a localizar rapidamente os dados e evitar varreduras completas da tabela.
-- Sem índice: varredura completa da tabela (buscar linha por linha)
SELECT * FROM employees WHERE last_name = 'Zhang';
-- Com índice: busca direta (via índice)
CREATE INDEX idx_last_name ON employees(last_name);
SELECT * FROM employees WHERE last_name = 'Zhang';
Criando Índices
-- Índice regular (permite valores duplicados)
CREATE INDEX idx_coluna ON nome_tabela(nome_coluna);
-- Índice único (não permite valores duplicados)
CREATE UNIQUE INDEX idx_coluna ON nome_tabela(nome_coluna);
-- Índice fulltext (para busca de texto completo)
CREATE FULLTEXT INDEX idx_coluna ON nome_tabela(nome_coluna);
-- Índice composto (combinação multi-coluna)
CREATE INDEX idx_colunas ON nome_tabela(coluna1, coluna2);
Excluindo Índices
-- Sintaxe MySQL
DROP INDEX idx_coluna ON nome_tabela;
-- Sintaxe padrão
ALTER TABLE nome_tabela DROP INDEX idx_coluna;
Tipos de Índice
| Tipo | Palavra-chave | Descrição | Caso de Uso |
|---|---|---|---|
| Índice Regular | INDEX |
Índice básico, permite valores duplicados | Colunas consultadas frequentemente |
| Índice Único | UNIQUE INDEX |
Valores da coluna devem ser únicos | E-mail, números de RG, etc. |
| Índice Fulltext | FULLTEXT INDEX |
Suporta busca de texto completo | Conteúdo de artigos, descrições de produtos |
| Índice Composto | INDEX(col1, col2) |
Índice de combinação multi-coluna | Consultas com múltiplas condições |
Índice Composto e Regra do Prefixo Mais à Esquerda
Índices compostos seguem a regra do prefixo mais à esquerda: condições de consulta devem corresponder da coluna mais à esquerda do índice para utilizá-lo.
-- Criar um índice composto
CREATE INDEX idx_name_age ON employees(last_name, first_name, salary);
-- ✅ Pode usar o índice (corresponde à coluna mais à esquerda)
SELECT * FROM employees WHERE last_name = 'Zhang';
SELECT * FROM employees WHERE last_name = 'Zhang' AND first_name = 'Wei';
-- ❌ Não pode usar o índice (pula a coluna mais à esquerda)
SELECT * FROM employees WHERE first_name = 'Wei';
SELECT * FROM employees WHERE salary > 10000;
Custo dos Índices
| Custo | Descrição |
|---|---|
| Espaço de armazenamento | Índices requerem espaço adicional em disco |
| Desempenho de escrita | INSERT/UPDATE/DELETE precisam sincronizar atualizações de índice |
| Custo de manutenção | Muitos índices reduzem a velocidade de escrita |
2. Sintaxe Básica
Sintaxe de Visualização
-- Criar uma visualização
CREATE [OR REPLACE] VIEW nome_visualizacao AS SELECT instrucao;
-- Consultar uma visualização (igual a uma tabela regular)
SELECT * FROM nome_visualizacao WHERE condicao;
-- Excluir uma visualização
DROP VIEW [IF EXISTS] nome_visualizacao;
v_ ou view_ para facilmente distingui-las de tabelas reais.
Sintaxe de Índice
-- Criar um índice
CREATE [UNIQUE|FULLTEXT] INDEX nome_indice ON nome_tabela(coluna1, coluna2, ...);
-- Excluir um índice
DROP INDEX nome_indice ON nome_tabela;
-- Visualizar índices de uma tabela
SHOW INDEX FROM nome_tabela;
EXPLAIN para verificar se uma consulta usa um índice: EXPLAIN SELECT * FROM employees WHERE last_name = 'Zhang';
Exemplo: Criando e Usando Visualizações (Dificuldade ⭐)
-- Criar uma visualização de detalhes do pedido
CREATE OR REPLACE VIEW v_order_detail AS
SELECT
o.order_id,
CONCAT(e.first_name, e.last_name) AS responsavel,
d.department_name AS departamento,
o.order_date,
o.total_amount AS valor,
o.status
FROM orders o
LEFT JOIN employees e ON o.employee_id = e.employee_id
LEFT JOIN departments d ON e.department_id = d.department_id;
-- Consultar usando a visualização
SELECT * FROM v_order_detail WHERE status = 'completed';
Saída:
order_id | responsavel | departamento | order_date | valor | status
---------+-------------+--------------+------------+---------+-----------
1001 | WangQiang | Sales | 2026-05-10 | 2500.00 | completed
1002 | WangQiang | Sales | 2026-05-15 | 1800.00 | completed
1005 | ZhaoMin | Sales | 2026-06-10 | 4100.00 | completed
-- Usar a visualização para agregar valores de pedidos por departamento
SELECT departamento, COUNT(*) AS qtd_pedidos, SUM(valor) AS valor_total
FROM v_order_detail
GROUP BY departamento;
Abordagem da consulta:
- A visualização encapsula a lógica complexa de JOIN de três tabelas
- Consultas simples são tudo que é necessário — não é necessário reescrever o JOIN
- Os resultados da visualização atualizam automaticamente conforme os dados subjacentes mudam
Exemplo: Criando Índices para Otimizar Desempenho de Consulta (Dificuldade ⭐⭐)
-- Visualizar o plano de execução da consulta atual
EXPLAIN SELECT * FROM employees WHERE last_name = 'Zhang';
Saída (sem índice):
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
| 1 | SIMPLE | employees | ALL | NULL | NULL | NULL | NULL | 6 | Using where |
+----+-------------+-----------+------+---------------+------+---------+------+------+-------+
type = ALL indica uma varredura completa da tabela, rows = 6 indica que todas as linhas foram escaneadas.
-- Criar um índice
CREATE INDEX idx_last_name ON employees(last_name);
-- Visualizar o plano de execução novamente
EXPLAIN SELECT * FROM employees WHERE last_name = 'Zhang';
Saída (com índice):
+----+-------------+-----------+------+---------------+---------------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------+------+---------------+---------------+---------+-------+------+-------+
| 1 | SIMPLE | employees | ref | idx_last_name | idx_last_name | 152 | const | 1 | |
+----+-------------+-----------+------+---------------+---------------+---------+-------+------+-------+
type = ref indica que o índice está sendo usado, rows = 1 indica que apenas 1 linha foi escaneada.
-- Criar um índice composto
CREATE INDEX idx_status_date ON orders(status, order_date);
-- Consulta que pode usar o índice
EXPLAIN SELECT * FROM orders WHERE status = 'completed' AND order_date > '2026-06-01';
-- Visualizar todos os índices de uma tabela
SHOW INDEX FROM employees;
Abordagem da consulta:
- Coluna
typedo EXPLAIN:ALL(varredura completa) →ref(referência de índice) indica melhoria de desempenho - Coluna
rows: menos linhas escaneadas é melhor - Índices compostos devem ser usados seguindo a regra do prefixo mais à esquerda
3. Cenários Comuns de Aplicação
Cenário 1: Simplificar Gerenciamento de Permissões com Visualizações
-- Criar uma visualização contendo apenas informações não sensíveis
CREATE OR REPLACE VIEW v_employee_public AS
SELECT
employee_id,
CONCAT(first_name, last_name) AS nome,
d.department_name AS departamento
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id;
-- Usuários comuns só podem acessar esta visualização, não salário ou outras informações sensíveis
SELECT * FROM v_employee_public;
Cenário 2: Implementar Relatórios de Dados com Visualizações
-- Criar uma visualização de relatório de vendas mensal
CREATE OR REPLACE VIEW v_monthly_sales AS
SELECT
DATE_FORMAT(order_date, '%Y-%m') AS mes,
COUNT(*) AS qtd_pedidos,
SUM(total_amount) AS total_vendas,
AVG(total_amount) AS valor_medio_pedido,
COUNT(DISTINCT customer_id) AS qtd_clientes
FROM orders
WHERE status != 'cancelled'
GROUP BY DATE_FORMAT(order_date, '%Y-%m');
-- Consultar o relatório
SELECT * FROM v_monthly_sales ORDER BY mes;
Saída:
mes | qtd_pedidos | total_vendas | valor_medio_pedido | qtd_clientes
--------+-------------+--------------+--------------------+-------------
2026-05 | 2 | 4300.00 | 2150.00 | 2
2026-06 | 3 | 8250.00 | 2750.00 | 3
❓ Perguntas Frequentes
P: Qual a diferença entre uma visualização e uma tabela temporária? R: Visualizações não armazenam dados — cada consulta executa o SQL subjacente, então os resultados estão sempre atualizados; tabelas temporárias armazenam instantâneos de dados, oferecendo consultas mais rápidas mas dados potencialmente desatualizados. Visualizações são adequadas para modelos de consulta de longo prazo, enquanto tabelas temporárias são adequadas para etapas de cálculo intermediário.
P: Visualizações podem modificar dados? R: Depende da definição da visualização. Visualizações contendo JOINs, funções de agregação, DISTINCT ou subconsultas geralmente não são atualizáveis (apenas SELECT). Visualizações simples de tabela única (sem agregação) podem ser atualizadas com UPDATE. Na prática, visualizações são usadas principalmente para consulta — modificar dados através de visualizações não é recomendado.
P: Mais índices são sempre melhores? R: Não. Índices consomem espaço de armazenamento e reduzem o desempenho de INSERT/UPDATE/DELETE. Crie índices apenas para colunas que são consultadas frequentemente e possuem alta cardinalidade (muitos valores distintos). Tabelas pequenas geralmente não precisam de índices.
P: Como posso saber se uma consulta está usando um índice? R: Use o comando
EXPLAINpara visualizar o plano de execução. Focando na colunatype:ALL(varredura completa, mais lento) →index→range→ref→eq_ref→const(mais rápido). SetypeforALLe a tabela tiver uma grande quantidade de dados, um índice pode ser necessário.
📖 Resumo
- Visualizações são tabelas virtuais que salvam consultas SELECT, não armazenam dados e sempre permanecem sincronizadas com as tabelas subjacentes
- Visualizações podem simplificar consultas complexas, controlar acesso a dados e padronizar lógica de consultas
- Visualizações contendo JOINs/agregação/DISTINCT geralmente não são atualizáveis
- Índices são o "sumário" do banco de dados — aceleram consultas mas adicionam sobrecarga de armazenamento e escrita
- Tipos de índice: índice regular, índice único, índice fulltext, índice composto
- Regra do prefixo mais à esquerda: consultas com índice composto devem corresponder da coluna mais à esquerda
- Use
EXPLAINpara analisar se uma consulta está usando um índice
📝 Exercícios
Exercício 1 (⭐): Crie uma visualização v_high_salary mostrando informações de funcionários (nome, salário, nome do departamento) para funcionários com salário acima de 10000, depois use a visualização para consultar funcionários de alto salário no departamento "Technology".
Exercício 2 (⭐⭐): Crie uma visualização v_department_report contendo nome do departamento, contagem de funcionários, salário médio, maior salário e menor salário. Depois use a visualização para encontrar o departamento com o maior salário médio.
Exercício 3 (⭐⭐): Crie um índice na coluna customer_id da tabela orders, e use EXPLAIN para comparar o desempenho da consulta antes e depois de criar o índice. Depois crie um índice composto em orders(status, order_date) e teste quais consultas podem utilizá-lo.
Próxima Lição
👉 18-practice-aggregate - Prática: Análise de Dados: Aplique funções de agregação, consultas com agrupamento, expressões condicionais e funções avançadas juntas para melhorar suas habilidades de análise de dados através de cenários práticos!



