SQL: Visualizações e Índices
Última atualização: 2026-10-09
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
(1) 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;
(2) 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;
(3) 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;
(4) Excluindo Visualizações
DROP VIEW IF EXISTS v_employee_info;
(5) 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 |
(6) 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 |
(7) Í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';
(8) 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);
(9) Excluindo Índices
-- Sintaxe MySQL
DROP INDEX idx_coluna ON nome_tabela;
-- Sintaxe padrão
ALTER TABLE nome_tabela DROP INDEX idx_coluna;
(10) 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 |
(11) Í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;
(12) 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
(1) 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.
(2) 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
(1) 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;
(2) 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
EXPLAIN para visualizar o plano de execução. Focando na coluna type: ALL (varredura completa, mais lento) → index → range → ref → eq_ref → const (mais rápido). Se type for ALL e 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.
4. Próxima Lição
👉 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!