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)
À 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
A preparação deve preservar significado, tempo de disponibilidade e âmbito de acesso antes de avaliar desempenho ou qualidade.
Referência: Professional Data Engineer standard exam guide · Current linked standard guide (document title v4.2); edition date unconfirmed (2026-09-30 inspection)