← Professional Data Engineer: pipelines e decisões de dados
12 / 15 · 135 MIN

Preparar análise, features históricas e partilha

Valida medidas, desempenho e acesso; reconstrói informação conhecida numa decisão e prepara partilha com contratos explícitos.

1. Definir a medida antes de acelerar o dashboard

Um dashboard deve responder a uma pergunta de negócio com uma medida definida. Regista unidade, granularidade, período, população incluída e tratamento de correções. Uma contagem de incidentes pode significar incidentes abertos, criados no período ou resolvidos no período; os resultados não são intercambiáveis. Num serviço APS fictício, a gestão quer tempo médio de resolução por incidente. Se a preparação guarda apenas médias por equipa, uma média simples dessas médias pode dar peso igual a equipas com volumes diferentes. Conserva soma e contagem para permitir recomposição correta da medida. Por exemplo, uma equipa tem soma 100 e contagem 10; outra tem soma 900 e contagem 30. A média por registo é 1000/40=25. A média simples de 10 e 30 seria 20 e responderia a outra pergunta. Escreve este contraexemplo no teste de aceitação do relatório. Acrescenta casos sem registos, incidentes reabertos e períodos ainda incompletos. Define também quando o resultado é provisório e quem aceita uma correção. Um gráfico mais rápido continua errado se a preparação alterou o significado da medida. Os exemplos desta aula são fictícios e não descrevem procedimentos BNP Paribas.

2. Relacionar otimização com evidência de execução

Começa a investigação de latência com jobs representativos e o plano de execução. Distingue tempo de consulta, espera, transferência e renderização no cliente. Procura trabalho repetido, joins que expandem a granularidade e transformação pesada aplicada mais vezes do que o necessário. Uma CTE melhora a organização da consulta, mas não garante materialização única. Se o plano mostra repetição, compara uma tabela temporária ou outro resultado intermédio adequado, incluindo custo de o produzir e conservar. Valida os resultados antes de comparar apenas duração. Materialized views e BI Engine resolvem problemas específicos. O tipo de materialized view condiciona capacidades; uma view não incremental não suporta smart tuning. Não generalizes uma funcionalidade a todas as variantes. Para BI Engine, consulta as estatísticas e motivos do job para perceber a aceleração efetiva. Uma reserva existente não demonstra benefício em cada consulta. Prepara uma comparação com o mesmo conjunto de dados, parâmetros e identidades, indicando cache e concorrência. Num fecho diário, inclui o pico de utilização em vez de medir apenas uma execução isolada. Regista quais os requisitos melhorados e quais permanecem por verificar, como frescura, compatibilidade com o consumidor e comportamento após atualização dos dados.

3. Validar segurança no percurso de consumo

O resultado de um controlo depende da identidade e do percurso usados. Uma conta com leitura integral não representa um consumidor que deve receber valores mascarados. Executa consultas representativas com as permissões efetivas do consumidor, incluindo colunas protegidas e combinações de filtros usadas no dashboard. Regista também a identidade do job de exportação. O facto de o ecrã mostrar dados mascarados não demonstra que outra conta produza um ficheiro mascarado. A aceitação deve observar o conteúdo efetivo que sai por cada percurso autorizado. Num caso fictício, o dashboard usa uma conta limitada e o batch de distribuição usa uma conta antiga com acesso integral. A equipa validou apenas o dashboard e está prestes a distribuir o ficheiro. Interrompe a conclusão de que ambos os percursos são equivalentes e compara configuração, permissões e saída. Se a exportação precisa de ter um âmbito reduzido, aplica e testa esse contrato na exportação. Não alteres permissões apenas para fazer o teste ficar verde. Mantém evidência de que o consumidor autorizado consegue executar o trabalho necessário e de que os campos excluídos não aparecem na saída destinada a esse consumidor. O proprietário deve aceitar qualquer mudança no âmbito partilhado.

4. Reconstruir o que era conhecido na decisão

Na preparação para ML, distingue quando uma informação era efetiva de quando ficou disponível. Uma correção pode descrever ontem e só chegar amanhã. Se o objetivo é avaliar uma decisão tomada hoje, usar essa correção dá ao modelo conhecimento que o serviço não tinha. Define a fronteira de disponibilidade, a entidade, a versão da transformação e a regra de escolha entre versões. Se o histórico não permite reconstruir esses elementos, regista a limitação. O simples uso de um timestamp não prova ausência de fuga de informação. No nosso exemplo APS, o modelo prioriza incidentes com uma feature que representa o estado operacional conhecido. O conjunto de treino deve ser preparado de acordo com esse contrato. Uma avaliação orientada ao futuro precisa de respeitar a sequência temporal relevante e de evitar reutilização indevida de exemplos. Compara também a transformação offline com a utilizada em produção. Substituir NULL por zero no treino e rejeitar NULL no serviço cria comportamentos diferentes perante o mesmo input. Mantém ausências e conflitos observáveis; não preenchas silenciosamente com informação futura para melhorar a métrica. A preparação correta não demonstra qualidade preditiva por si só, mas é necessária para que a avaliação tenha um significado útil.

5. Preparar documentos para recuperação útil

Embeddings e pesquisa vetorial também precisam de um contrato de preparação. Regista origem, versão do documento, segmentação, modelo, normalização e critérios de acesso ao conteúdo. Um vetor com o número esperado de componentes pode pertencer a uma representação incompatível com a usada no índice. Antes de mudar modelo ou preparação, mede a recuperação num conjunto de perguntas representativas, com documentos relevantes identificados. Sucesso HTTP da geração de embeddings não demonstra que os resultados úteis continuam a aparecer. Um índice aproximado pode reduzir latência e perder alguns vizinhos relevantes. Compara recall e duração em conjunto, incluindo perguntas difíceis e documentos recentemente atualizados. Num exemplo fictício de apoio ao RUN, o utilizador procura o procedimento aplicável à versão atual do middleware. Encontrar depressa um procedimento antigo pode piorar a decisão. Mantém data, versão e ligação ao documento original no resultado. Testa a atualização e remoção de conteúdo do conjunto pesquisável e o âmbito de acesso do consumidor. A seleção dos melhores resultados deve considerar o requisito operacional e a evidência disponível; um valor de similaridade elevado não prova que a instrução é atual nem que o utilizador está autorizado a lê-la.

6. Laboratório: seleção histórica com dois tempos

O programa original content/labs/pde-feature-history/run.py usa apenas Python local. Executa python3 content/labs/pde-feature-history/run.py < content/labs/pde-feature-history/case.json na raiz do projeto. features contém id, entity, effectiveAt, availableAt e value. decisions contém id, entity e at. Os tempos são inteiros numa escala fictícia; o valor é um inteiro sem significado financeiro ou clínico. Cada coleção tem IDs únicos e um máximo de 1000 entradas. O programa rejeita campos inesperados, identificadores inválidos, números fora dos limites e campos JSON repetidos. Para cada decisão, a seleção asKnownThen considera a mesma entidade e exige effectiveAt <= at e availableAt <= at. Ordena primeiro por effectiveAt e depois por availableAt, escolhendo os maiores valores elegíveis. Se várias linhas empatam e declaram o mesmo valor, conserva todos os IDs como proveniência. Se os valores diferem, devolve ambiguous e nenhum valor. Sem candidatos devolve missing. A seleção ignoringAvailability ignora a segunda condição para construir um contraexemplo. O programa compara as seleções, incluindo IDs e estado; uma mudança de proveniência pode ser assinalada mesmo com valor igual. Não treina modelos nem simula um feature store gerido.

7. Prever os resultados e testar as fronteiras

No exemplo, old tem tempos 10/10 e valor 5. known tem 20/40 e valor 6. correction tem 20/120 e valor 9. future tem 110/80 e valor 11. A decisão D1 ocorre em 100: known é a versão elegível escolhida, com valor 6; ignorar disponibilidade escolhe correction, com valor 9. future já estava disponível mas ainda não era efetiva e fica excluída. D2 ocorre em 30 e escolhe old; D3 pertence a outra entidade e devolve missing. Segue estas escolhas manualmente antes de executar o ficheiro. Depois acrescenta uma linha com os mesmos tempos de known e valor 7. A seleção histórica fica ambiguous. Troca a ordem das linhas e confirma que o resultado não muda. Se a linha empatada também tiver valor 6, a seleção conserva os dois IDs. Muda a decisão para 40 para observar a fronteira inclusiva de disponibilidade; muda-a para 110 para observar a fronteira efetiva. Aos 130, future continua a ganhar porque a regra dá prioridade ao tempo efetivo. Explica o motivo de cada resultado. Nenhum desses testes autentica os timestamps da origem nem demonstra qualidade do modelo que viria a consumir a feature.

8. Partilhar e entregar com significado preservado

A partilha precisa de um contrato que continue a ser compreendido pelos consumidores. Um linked dataset de BigQuery sharing é uma referência de leitura aos dados partilhados; a subscrição não cria uma cópia independente editável. Se o produtor muda a unidade de amount de cêntimos para euros mantendo o nome, os consumidores podem continuar a aplicar uma divisão por 100. Identifica dependências, versiona mudanças incompatíveis e valida a migração. Não confundas descoberta da listing com aprovação de qualquer utilização ou alteração futura. Na passagem a RUN, reúne definições das medidas, versão da preparação, evidência de desempenho, identidades autorizadas e tratamento de dados ausentes, atrasados ou conflitantes. Define quem responde quando uma métrica muda por correção histórica e quando a alteração deve ser comunicada. Para um produto de ML ou recuperação documental, conserva os critérios de avaliação e as limitações conhecidas. A equipa deve conseguir explicar o que foi medido, em que população, com que informação e para que consumidor. O resumo desta aula é ligar preparação à decisão: uma consulta rápida, uma métrica elevada ou uma partilha acessível só são úteis quando o conteúdo, o tempo e o âmbito de acesso correspondem ao contrato aceite.

"""Original offline feature-history contract; not a managed feature store."""
import json
import re
import sys


def exact(value, keys):
    if type(value) is not dict or set(value) != set(keys):
        raise ValueError('unexpected or missing fields')


def identifier(value):
    if type(value) is not str or not re.fullmatch(r'[A-Za-z0-9_-]{1,64}', value):
        raise ValueError('invalid identifier')


def integer(value, low, high):
    if type(value) is not int or not low <= value <= high:
        raise ValueError('integer outside local contract')


def select(candidates):
    if not candidates:
        return {'status': 'missing', 'ids': [], 'value': None}
    rank = max((r['effectiveAt'], r['availableAt']) for r in candidates)
    latest = [r for r in candidates if (r['effectiveAt'], r['availableAt']) == rank]
    values = {r['value'] for r in latest}
    return {'status': 'selected' if len(values) == 1 else 'ambiguous',
            'ids': sorted(r['id'] for r in latest),
            'value': latest[0]['value'] if len(values) == 1 else None}


def evaluate(document):
    exact(document, ['features', 'decisions'])
    features, decisions = document['features'], document['decisions']
    if type(features) is not list or len(features) > 1000:
        raise ValueError('at most 1000 feature rows required')
    if type(decisions) is not list or len(decisions) > 1000:
        raise ValueError('at most 1000 decisions required')
    for rows, keys in [(features, ['id','entity','effectiveAt','availableAt','value']),
                       (decisions, ['id','entity','at'])]:
        seen = set()
        for row in rows:
            exact(row, keys)
            identifier(row['id'])
            identifier(row['entity'])
            if row['id'] in seen:
                raise ValueError('duplicate id within collection')
            seen.add(row['id'])
            for key in ['effectiveAt','availableAt'] if rows is features else ['at']:
                integer(row[key], 0, 10**9)
            if rows is features:
                integer(row['value'], -10**6, 10**6)
    results = []
    for decision in sorted(decisions, key=lambda r: r['id']):
        candidates = [r for r in features if r['entity'] == decision['entity'] and r['effectiveAt'] <= decision['at']]
        available = [r for r in candidates if r['availableAt'] <= decision['at']]
        safe, naive = select(available), select(candidates)
        results.append({'decisionId': decision['id'], 'at': decision['at'],
                        'asKnownThen': safe, 'ignoringAvailability': naive,
                        'excludedUnavailableIds': sorted(r['id'] for r in candidates if r['availableAt'] > decision['at']),
                        'selectionDiffers': safe != naive})
    return {'results': results, 'contract': 'latest effectiveAt, then latest availableAt, both <= decision time',
            'sourceTimestampAuthenticityProven': False, 'modelQualityProven': False,
            'cloudExecutionValidated': False, 'productionApproval': False}


def unique_object(pairs):
    result = {}
    for key, value in pairs:
        if key in result:
            raise ValueError('duplicate JSON field')
        result[key] = value
    return result


if __name__ == '__main__':
    try:
        raw = sys.stdin.read(1_000_001)
        if len(raw) > 1_000_000:
            raise ValueError('input exceeds local limit')
        print(json.dumps(evaluate(json.loads(raw, object_pairs_hook=unique_object)), sort_keys=True))
    except (ValueError, TypeError, RecursionError) as error:
        print(json.dumps({'error': str(error)}), file=sys.stderr)
        sys.exit(2)
NA PRÁTICA

À decisão 100, a versão disponível vale 6; ignorar availableAt escolhe uma correção posterior de valor 9.

Armadilhas comuns

Média de médias sem pesos; reserva como prova de aceleração; correções futuras no treino; teste de masking com outra identidade.

Tópicos relacionados: Fidelidade do armazenamento · Operação e observabilidade · Governação de dados

Leva esta ideia contigo

A preparação deve preservar significado, tempo de disponibilidade e âmbito de acesso antes de avaliar desempenho ou qualidade.

Criar conta

Referência: Professional Data Engineer standard exam guide · Current linked standard guide (document title v4.2); edition date unconfirmed (2026-09-30 inspection)

Google Cloud é uma marca comercial de Google LLC. A dr.pt é uma plataforma de preparação independente e não está afiliada, associada, patrocinada, autorizada nem aprovada por Google. Os conteúdos e as perguntas são originais, não são perguntas oficiais de exame, e concluir os nossos testes não atribui nem garante qualquer certificação. Os nomes são usados apenas para identificar o tema. Todas as outras marcas pertencem aos respetivos titulares.