← Voltar a Data Engineer — Indicium-AI

🔴 Data Migration — CRÍTICO

Data Engineer — Indicium-AI

Apresentação

🔄 Data Migration — Guia Completo

Foco principal da entrevista Indicium-AI. Estratégias, desafios, ferramentas, validação e exercícios de código.


PARTE I — Estratégias e Conceitos

1. Big Bang vs Phased (incremental)

Big BangPhased
O quêMigrar tudo de uma vezMigrar por módulos/incrementos
DowntimeJanela única, maiorMúltiplas janelas menores ou zero
RiscoAlto — tudo ou nadaBaixo — falha isolada
QuandoSistema pequeno (<100GB), janela aceitávelSistema grande, zero-downtime desejado
RollbackDifícil — restaurar tudoMais fácil — só o último incremento
ComplexidadeMenor coordenaçãoMaior — dependências entre módulos

Exemplo Phased: Migrar primeiro dim_customer, depois dim_product, depois fact_sales. Cada fase valida antes da próxima.


2. Lift-and-shift vs Refactor

  • Lift-and-shift: Migrar tal qual. Rápido (semanas), mas arrasta schema antigo, débito técnico, problemas de performance.
  • Refactor: Redesenhar durante migração. Normalizado → Star/Snowflake. Mais tempo (meses), schema moderno.
  • Híbrido: Lift-and-shift para Bronze; refactor em Silver/Gold. Abordagem pragmática.

3. Parallel run e Blue-Green

Parallel run

  • Correr sistema antigo e novo em paralelo durante 1–4 semanas.
  • Comparar outputs: row count, checksums, amostragem, queries de negócio.
  • Cutover só quando confiança total. Útil antes de Big Bang.

Blue-Green

  • Ambiente novo (Green) pronto e validado.
  • Switch de tráfego/APIs para Green.
  • Blue fica como fallback imediato se algo falhar.

PARTE II — Desafios em Migração

4. Schema mapping (legacy → modern)

Problemas:

  • Tabelas normalizadas (3NF) → Star/Snowflake dimensional?
  • Campos com nomes diferentes (cust_id vs customer_id)
  • Tipos diferentes (VARCHAR(10) vs INT, datas em formatos distintos)
  • Colunas que não existem no destino (como mapear?)

Abordagem:

  1. Documentar mapeamento: origem.coluna → destino.coluna (incluir transformações)
  2. Scripts de transformação (SQL, Spark, dbt)
  3. Staging intermediário para validar antes de Gold

5. Data quality (dados sujos na origem)

Problemas comuns:

  • NULLs onde não deviam existir
  • Formatos inconsistentes (telefone: "912345678" vs "+351 912 345 678")
  • Duplicados (mesmo cliente com IDs diferentes)
  • Valores fora de range (idade = 999)
  • Encoding (caracteres corrompidos)

Abordagem:

  1. Profiling antes: Great Expectations, Pandas Profiler, queries de análise
  2. Regras de validação: not null, formatos, ranges
  3. Silver layer: limpeza, defaults para NULLs, deduplicação
  4. Documentar exceções: "10 registos com email inválido — mantidos em Bronze, excluídos de Silver"

6. Downtime e janelas de cutover

  • Big Bang: Janela única (ex: 4h no domingo). Backup, restore testado, procedimento escrito.
  • Phased: Janelas menores (ex: 1h por módulo). Mais complexidade de coordenação.
  • Zero-downtime: CDC contínuo + dual-write temporário + switch de leitura.

7. Rollback — plano B

O que incluir:

  • Backup completo antes do cutover
  • Procedimento documentado (passo a passo) para reverter
  • Se phased: reverter só o último incremento
  • Comunicação com stakeholders (quem decide reverter?)
  • Teste do rollback em ambiente de staging

8. Volume e performance

Migrar TB em tempo aceitável:

  • Paralelismo: Múltiplos workers, particionar por range (ex: por data)
  • Batch em chunks: Migrar 1M linhas de cada vez, não tudo de uma vez
  • CDC: Para dados que mudam frequentemente — evita full reload
  • Compressão: Parquet/Delta em vez de CSV
  • Índices: Criar após carga, não durante

PARTE III — Ferramentas e Abordagens

9. CDC (Change Data Capture)

O quê: Captura inserts, updates, deletes em tempo (quase) real.

Ferramentas:

  • Debezium: Open-source, Kafka Connect, suporta PostgreSQL, MySQL, etc.
  • AWS DMS: Managed, suporta muitas fontes e destinos
  • Fivetran: Managed, CDC automático para várias fontes

Quando usar: Dados transacionais que mudam frequentemente; sincronização contínua; reduz volume vs full load.

Desafios: Ordem dos eventos, schema evolution, performance na origem (logs).


10. ETL/ELT para migração

FerramentaUsoPrósContras
Fivetran, AirbyteConectores managedPouco código, rápidoMenos controlo, custo
Custom SparkVolume grande, transformações complexasControlo totalMais desenvolvimento
dbtTransformações no destino (ELT)Versionamento, testesPrecisa de dados já carregados
Azure Data Factory, FabricOrquestração, pipelinesIntegração MicrosoftLock-in

11. Validação pós-migração

  1. Row count: SELECT COUNT(*) origem vs destino (por tabela, por partição)
  2. Checksums: MD5(CONCAT(col1, col2, ...)) ou CHECKSUM_AGG — hash de linhas
  3. Amostragem: Comparar N linhas aleatórias (ex: 1000) — valores exatos
  4. Reconciliação: Queries de negócio — "total vendas por mês" deve ser igual
  5. Referential integrity: FKs válidas (fact.customer_id existe em dim_customer?)

PARTE IV — Modelação em Contexto de Migração

12. Redesenhar schema

Normalizado (3NF) → Dimensional (Star):

  • Identificar entidades de negócio → dimensões
  • Identificar eventos/transações → fact tables
  • Desnormalizar dimensões (redundância aceitável para performance)
  • Criar surrogate keys se necessário

13. SCD ao migrar dimensões

SCD Type 2 em migração:

  • Origem pode não ter valid_from/valid_to
  • Inferir histórico: se há múltiplas linhas por id, tratar como Type 2
  • Ou: migrar como Type 1 primeiro, evoluir para Type 2 depois

14. Tratamento de duplicados

  • Chave natural vs surrogate: Definir chave para dedup (ex: email + nome)
  • Estratégia: Manter mais recente (ORDER BY updated_at DESC), ou merge (coalesce de colunas)

PARTE V — Código e Exercícios

15. Padrões SQL para migração

Deduplicação (manter mais recente)

WITH ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) AS rn
  FROM source_table
)
SELECT * FROM ranked WHERE rn = 1;

Deduplicação por múltiplas colunas (chave composta)

WITH ranked AS (
  SELECT *, ROW_NUMBER() OVER (
    PARTITION BY customer_id, product_id 
    ORDER BY transaction_date DESC
  ) AS rn
  FROM sales_raw
)
SELECT * FROM ranked WHERE rn = 1;

Checksum para validação

-- Origem
SELECT COUNT(*), SUM(CHECKSUM(col1, col2, col3)) FROM origem;

-- Destino
SELECT COUNT(*), SUM(CHECKSUM(col1, col2, col3)) FROM destino;
-- Valores devem coincidir

Row count por partição

SELECT partition_col, COUNT(*) 
FROM tabela 
GROUP BY partition_col
ORDER BY partition_col;

Top-N por grupo (útil para amostragem)

SELECT * FROM (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY category ORDER BY amount DESC) AS rn
  FROM products
) WHERE rn <= 3;

16. Pseudo-código Python para migração

Batch em chunks

def migrate_in_chunks(source_conn, dest_conn, table, chunk_size=100000):
    offset = 0
    while True:
        batch = source_conn.execute(
            f"SELECT * FROM {table} ORDER BY id LIMIT {chunk_size} OFFSET {offset}"
        )
        if not batch:
            break
        dest_conn.insert_batch(table, batch)
        offset += chunk_size

Validação row count

def validate_row_count(source, dest, tables):
    for table in tables:
        src_count = source.execute(f"SELECT COUNT(*) FROM {table}").scalar()
        dst_count = dest.execute(f"SELECT COUNT(*) FROM {table}").scalar()
        assert src_count == dst_count, f"{table}: {src_count} != {dst_count}"

Merge/upsert (idempotência)

# Pseudo: para cada batch, fazer MERGE em vez de INSERT
# MERGE dest USING source ON dest.id = source.id
# WHEN MATCHED THEN UPDATE SET ...
# WHEN NOT MATCHED THEN INSERT ...

17. Cenários de whiteboard

"Descreve o plano de migração de um DW legado para Lakehouse"

  1. Profiling (schema, volumetria, qualidade)
  2. Mapeamento (documento origem → destino)
  3. Bronze: raw load (batch ou CDC)
  4. Silver: limpeza, dedup, validação
  5. Gold: modelo dimensional, agregados
  6. Validação: row count, checksum, amostragem
  7. Cutover + rollback plan

"Como migrarias 10TB em 8 horas?"

  • Paralelismo: N workers (ex: 8)
  • Particionar por chave (data, id range)
  • Cada worker: chunk de ~1.25TB
  • Formato comprimido (Parquet)
  • Rede e I/O como bottleneck — medir throughput

"A origem tem 5% de duplicados. O que fazes?"

  • Profiling para identificar padrão (quais colunas definem duplicado?)
  • Dedup em Silver com ROW_NUMBER
  • Documentar regra (ex: manter updated_at mais recente)
  • Validar que contagens fazem sentido após dedup

PARTE VI — Frases que Impressionam

  • "Sempre tenho um plano de rollback documentado antes do cutover."
  • "Profiling antes de migrar — conhecer a qualidade dos dados na origem evita surpresas."
  • "CDC quando os dados mudam frequentemente; full load quando é histórico estático."
  • "Bronze imutável, Silver onde limpamos — nunca perdemos o raw."
  • "Validação em camadas: row count, checksum, amostragem, reconciliação de negócio."
  • "Idempotência na migração: MERGE em vez de INSERT para que retries não dupliquem dados."

PARTE VII — Perguntas Técnicas Avançadas

18. Zero-downtime migration

Como conseguir?

  • CDC contínuo para o novo sistema (já a receber dados)
  • Dual-write temporário: aplicação escreve em ambos (antigo + novo)
  • Período de sync: CDC + dual-write até destinos iguais
  • Switch de leitura para novo; desligar dual-write

19. Data Vault em migração

  • Hubs: Entidades de negócio (customer, product)
  • Satellites: Atributos ao longo do tempo (SCD implícito)
  • Links: Relações entre hubs (vendas = link customer-product-date)
  • Migração: mapear tabelas normalizadas para Hubs/Sats/Links; histórico preservado naturalmente

20. Tratamento de dados sensíveis (PII)

  • Antes de migrar: Mascarar ou pseudonimizar em staging
  • Colunas: Nome, email, telefone, IBAN
  • Ferramentas: dbt com macros, scripts custom, AWS DMS com transformações
  • Nunca carregar PII em claro para ambiente de dev/test

21. Performance: por que a migração está lenta?

Diagnóstico:

  • Rede (throughput entre origem e destino)
  • I/O disco (leitura na origem, escrita no destino)
  • Transformações (joins pesados, sem particionamento)
  • Locks/contention na origem (SELECT bloqueado por writes)
  • Soluções: Paralelismo, batch menor, índices temporários, ler de réplica

22. Orquestração da migração

  • Airflow/Fabric: DAG com tarefas: extract → transform → load → validate
  • Ordem: Dimensões antes de facts (integridade referencial)
  • Retry: Configurar para falhas transitórias
  • Alertas: Slack/email se validação falhar

23. Testes antes do cutover

  • Migração em ambiente de staging (cópia da origem)
  • Run completo + validação
  • Medir tempo real
  • Dry-run do rollback
  • Checklist assinado por stakeholders

24. Resolução de conflitos (CDC)

  • Ordem: Processar eventos por timestamp
  • Updates concorrentes: Last-write-wins ou merge de colunas
  • Deletes: Soft delete vs hard delete no destino
  • Schema evolution: Nova coluna — backfill ou default

PARTE VIII — Resumo Rápido (Cheat Sheet)

ConceitoResposta em 30s
Big Bang vs PhasedBig Bang: tudo de uma vez, risco alto. Phased: por módulos, rollback fácil.
ValidaçãoRow count, checksum, amostragem, reconciliação negócio
CDC vs Full loadCDC: dados que mudam. Full: histórico estático
DedupROW_NUMBER() OVER (PARTITION BY key ORDER BY ts DESC) WHERE rn=1
RollbackBackup + procedimento + comunicação
Bronze/Silver/GoldRaw → Limpo → Negócio
IdempotênciaMERGE, chave única, truncate+load

Zona de prática

Sem perguntas. Clica em Editar para adicionar.

Desafios de código

Deduplicação por id (SQL)

Escreve a query para deduplicar por id, mantendo o registo mais recente (por updated_at).

Validação por checksum (SQL)

Escreve a lógica para comparar checksum entre origem e destino (count + hash).

Top 3 vendas por cliente (SQL)

Usa ROW_NUMBER para obter as 3 maiores vendas de cada cliente.

Migração em chunks (pseudo-código Python)

Escreve a lógica para migrar uma tabela em batches de 100k linhas.

Validação row count (pseudo-código)

Função que valida que count(*) é igual em origem e destino para uma lista de tabelas.

SCD Type 2 — nova linha (SQL)

Dado um update num cliente (região mudou), como inserir nova linha e fechar a antiga?

MERGE/upsert (SQL)

Escreve um MERGE que insere linhas novas e atualiza existentes (id como chave).

Comparação mês a mês (SQL)

Usa LAG para calcular variação de vendas: este mês vs mês anterior.