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