Início / Trilha 4 / Conteúdo / Tópico 3
3

Otimização de Índices

Tipos, criação, manutenção e quando usar

📖

Definição

Tipos de Índices Oracle

B-Tree (Padrão)

Estrutura de árvore balanceada. Ideal para alta cardinalidade (muitos valores distintos). Usado em 90% dos casos: colunas de ID, datas, nomes, códigos.

CREATE INDEX idx_employees_email ON employees(email);
CREATE UNIQUE INDEX idx_emp_cpf ON employees(cpf);

Bitmap

Para baixa cardinalidade (poucos valores distintos). Comum em Data Warehouse. Não use em OLTP (alto custo de manutenção com INSERTs/UPDATEs).

-- Bom para: sexo (M/F), status (A/I), departamento (10 valores)
CREATE BITMAP INDEX idx_emp_gender ON employees(gender);
CREATE BITMAP INDEX idx_prod_category ON products(category_id);

Function-Based

Indexa resultado de função aplicada à coluna. Necessário quando query usa função no WHERE.

-- Para queries com UPPER(), LOWER(), TO_DATE(), etc
CREATE INDEX idx_emp_upper_name ON employees(UPPER(name));
CREATE INDEX idx_ord_year ON orders(EXTRACT(YEAR FROM order_date));

Composite (Múltiplas Colunas)

Índice em várias colunas. Ordem é CRÍTICA: coluna mais seletiva primeiro. Usado em queries com múltiplos filtros.

-- Para: WHERE dept_id = 10 AND status = 'A'
CREATE INDEX idx_emp_dept_status ON employees(department_id, status);

-- Ordem importa! Este índice serve para:
-- WHERE department_id = X (usa índice)
-- WHERE department_id = X AND status = Y (usa índice completo)
-- WHERE status = Y (NÃO usa o índice - status não é a primeira coluna)
🛠️

Aplicação Prática

Monitorando Índices

-- Ver todos os índices de uma tabela
SELECT
    index_name,
    index_type,
    uniqueness,
    status,
    num_rows,
    distinct_keys,
    blevel,                    -- Profundidade da árvore (ideal: 2-3)
    leaf_blocks,               -- Blocos folha
    clustering_factor          -- Quão organizado está (quanto menor, melhor)
FROM dba_indexes
WHERE table_name = 'EMPLOYEES';

-- Ver colunas de cada índice
SELECT
    index_name,
    column_name,
    column_position,
    descend
FROM dba_ind_columns
WHERE table_name = 'EMPLOYEES'
ORDER BY index_name, column_position;

-- Monitorar uso de índices (12c+)
ALTER INDEX idx_employees_email MONITORING USAGE;

-- Após algumas horas/dias, verificar
SELECT * FROM v$object_usage WHERE index_name = 'IDX_EMPLOYEES_EMAIL';

-- Identificar índices não usados (candidatos a DROP)
SELECT
    index_name,
    table_name,
    used,
    start_monitoring,
    end_monitoring
FROM v$object_usage
WHERE used = 'NO' AND monitoring = 'YES';

Manutenção de Índices

-- Verificar fragmentação
SELECT
    index_name,
    blevel,                               -- > 4 indica problema
    leaf_blocks,
    (del_lf_rows / NULLIF(lf_rows, 0)) * 100 AS pct_deleted,  -- > 20% = fragmentado
    height,
    pct_used
FROM dba_ind_statistics
WHERE table_name = 'EMPLOYEES';

-- Rebuild índice (recria estrutura, otimiza espaço)
ALTER INDEX idx_employees_email REBUILD ONLINE;  -- ONLINE mantém acesso durante rebuild

-- Rebuild em paralelo (mais rápido)
ALTER INDEX idx_employees_dept REBUILD ONLINE PARALLEL 4;
ALTER INDEX idx_employees_dept NOPARALLEL;  -- Volta ao padrão após rebuild

-- Coalesce (reorganiza sem recriar - mais rápido que rebuild)
ALTER INDEX idx_employees_email COALESCE;

-- Rebuild de todos os índices de uma tablespace
SELECT 'ALTER INDEX ' || index_name || ' REBUILD ONLINE;'
FROM dba_indexes
WHERE tablespace_name = 'USERS'
  AND status = 'VALID';

-- Atualizar estatísticas de índices
EXEC DBMS_STATS.GATHER_INDEX_STATS('SCHEMA_NAME', 'IDX_EMPLOYEES_EMAIL');

-- Validar estrutura de índice
ANALYZE INDEX idx_employees_email VALIDATE STRUCTURE;

Decisões: Criar ou Não Criar?

Quando CRIAR índice

  • Colunas em WHERE frequentes
  • Colunas de JOIN
  • Colunas de ORDER BY
  • Foreign Keys (sempre!)
  • Queries lentas com full scan
  • Tabelas grandes (>100k linhas)
  • Alta seletividade (retorna <5% da tabela)

Quando NÃO criar índice

  • Tabelas pequenas (<1000 linhas)
  • Colunas com baixa cardinalidade (OLTP)
  • Colunas raramente filtradas
  • Tabela com muitos INSERTs (overhead)
  • Query retorna >10% da tabela
  • Já existe índice composto que serve
  • Índice duplicado/redundante

Regra de Ouro:

Índices aceleram SELECT mas tornam INSERT/UPDATE/DELETE mais lentos (overhead de manutenção). Balanceie conforme workload: OLTP = poucos índices seletivos; DW = mais índices, inclusive bitmaps.

✅

Resultado Esperado

✓

Escolher tipo correto

B-tree, bitmap, function-based, composite

✓

Criar índices eficientes

Ordem correta em composites, ONLINE rebuild

✓

Monitorar uso

Identificar índices não utilizados

✓

Detectar fragmentação

BLEVEL, deleted entries, clustering factor

✓

Fazer manutenção

REBUILD, COALESCE quando necessário

✓

Remover índices desnecessários

Reduzir overhead de manutenção

Anterior: Planos de Execução Próximo: Tuning de SQL