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 Bang | Phased | |
|---|---|---|
| O quê | Migrar tudo de uma vez | Migrar por módulos/incrementos |
| Downtime | Janela única, maior | Múltiplas janelas menores ou zero |
| Risco | Alto — tudo ou nada | Baixo — falha isolada |
| Quando | Sistema pequeno (<100GB), janela aceitável | Sistema grande, zero-downtime desejado |
| Rollback | Difícil — restaurar tudo | Mais fácil — só o último incremento |
| Complexidade | Menor coordenação | Maior — 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:
- Documentar mapeamento:
origem.coluna → destino.coluna(incluir transformações) - Scripts de transformação (SQL, Spark, dbt)
- 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:
- Profiling antes: Great Expectations, Pandas Profiler, queries de análise
- Regras de validação: not null, formatos, ranges
- Silver layer: limpeza, defaults para NULLs, deduplicação
- 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
| Ferramenta | Uso | Prós | Contras |
|---|---|---|---|
| Fivetran, Airbyte | Conectores managed | Pouco código, rápido | Menos controlo, custo |
| Custom Spark | Volume grande, transformações complexas | Controlo total | Mais desenvolvimento |
| dbt | Transformações no destino (ELT) | Versionamento, testes | Precisa de dados já carregados |
| Azure Data Factory, Fabric | Orquestração, pipelines | Integração Microsoft | Lock-in |
11. Validação pós-migração
- Row count:
SELECT COUNT(*)origem vs destino (por tabela, por partição) - Checksums:
MD5(CONCAT(col1, col2, ...))ouCHECKSUM_AGG— hash de linhas - Amostragem: Comparar N linhas aleatórias (ex: 1000) — valores exatos
- Reconciliação: Queries de negócio — "total vendas por mês" deve ser igual
- 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"
- Profiling (schema, volumetria, qualidade)
- Mapeamento (documento origem → destino)
- Bronze: raw load (batch ou CDC)
- Silver: limpeza, dedup, validação
- Gold: modelo dimensional, agregados
- Validação: row count, checksum, amostragem
- 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)
| Conceito | Resposta em 30s |
|---|---|
| Big Bang vs Phased | Big Bang: tudo de uma vez, risco alto. Phased: por módulos, rollback fácil. |
| Validação | Row count, checksum, amostragem, reconciliação negócio |
| CDC vs Full load | CDC: dados que mudam. Full: histórico estático |
| Dedup | ROW_NUMBER() OVER (PARTITION BY key ORDER BY ts DESC) WHERE rn=1 |
| Rollback | Backup + procedimento + comunicação |
| Bronze/Silver/Gold | Raw → Limpo → Negócio |
| Idempotência | MERGE, 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.