Implementando Soluções de Engenharia de Dados com Microsoft Fabric
Um guia de estudo completo, objetivo por objetivo, construído a partir do Microsoft Learn. Cada título abaixo corresponde a um item do skills outline oficial, então você pode percorrer o outline de cima a baixo com a certeza de não deixar nada de fora.
- Certificação
- Fabric Data Engineer Associate
- Nota de aprovação
- 700 / 1000
- Linguagens
- KQL · T-SQL · PySpark
- Renovação
- Gratuita, anual, online
Como usar este guia
Os três domínios têm peso igual. Isso é incomum, e é o fato mais útil para planejar o DP-700: não existe um domínio "grande" em que valha a pena investir demais, nem um pequeno que dê para pular. Monitoramento e otimização vale exatamente o mesmo que ingestão.
O exame é escrito para quem já constrói soluções de dados e agora precisa tomar decisões específicas do Fabric. A maioria das questões não é "o que o OPTIMIZE faz" — é "dadas estas restrições, qual destes quatro itens do Fabric você usa, e por que não os outros três". Por isso as tabelas de decisão deste guia importam mais do que a sintaxe, e ambas importam mais do que decorar caminhos de menu.
Leia Fundamentos do Fabric primeiro, mesmo não sendo um domínio do exame — capacity, OneLake e a taxonomia de itens são o vocabulário em que todas as outras respostas são escritas. Depois trabalhe o Domínio 2 (o mais prático), então o Domínio 1 e por último o Domínio 3, porque as questões do Domínio 3 pressupõem que você já sabe o que são um Spark pool, um Dataflow e um Eventhouse.
Os quatro formatos de questão que você vai encontrar
Escolher o item certo
"Você precisa ingerir 200 GB por noite do Snowflake sem código. O que usar?" A resposta está numa tabela de decisão, não na sintaxe. Elimine sempre por persona, latência, complexidade da transformação e custo.
Completar o código
Arrastar-e-soltar ou preencher KQL, T-SQL ou PySpark. Normalmente 3 a 6 linhas. A pegadinha quase sempre é a ordem dos operadores (KQL) ou um ramo WHEN MATCHED ausente (MERGE em T-SQL).
Diagnosticar a falha
Um sintoma mais os logs. Você escolhe a causa ou a correção. Decore as mensagens de erro: HTTP 430, CapacityLimitExceeded, falha de conversão de schema, credencial de shortcut expirada.
Ordenar as etapas
Sequenciar uma conexão Git, uma promoção de deployment pipeline ou uma configuração de segurança. O Fabric tem pré-requisitos rígidos (por exemplo, workspace identity antes de trusted workspace access) — é aí que está a pegadinha.
A Microsoft atualiza o DP-700 mais ou menos a cada seis meses, e recursos em preview aparecem. Onde este guia marca algo como Preview, saiba o que é e que problema resolve — ninguém vai perguntar a data de GA.
Fundamentos do Fabric (o vocabulário)
Capacity, CUs, bursting e smoothing
Tudo no Fabric roda sobre uma capacity — um pool de computação medido em Capacity Units (CU), comprado como SKU F (F2 → F2048) ou herdado de um SKU P do Power BI. Uma capacity pertence a uma região; workspaces são atribuídos a uma capacity. Se você pausar a capacity, tudo dentro dela para, inclusive a replicação de mirroring.
| Conceito | O que significa | Por que o exame cobra |
|---|---|---|
| Bursting | Um job pode consumir temporariamente mais computação do que o SKU nominalmente oferece, para terminar rápido. | Explica por que um job Spark grande roda numa SKU pequena. |
| Smoothing | O consumo de CU é distribuído ao longo do tempo — operações interativas em 5–64 minutos, background em 24 horas. | Explica por que o mesmo job aparece como um pico pequeno no Metrics app. |
| Timepoint | Um intervalo de avaliação de 30 segundos. 2.880 timepoints por dia. | É a unidade que o Capacity Metrics app plota. |
| Carryforward | Dívida de CU não paga, empurrada para timepoints futuros quando você gasta demais. | É o que acaba disparando o throttling. |
O throttling é uma penalidade em estágios, aplicada contra o consumo futuro suavizado:
| Uso futuro devido | Estágio | Efeito |
|---|---|---|
| ≤ 10 minutos | Overage protection | Nada. Margem livre de burst. |
| 10 – 60 minutos | Interactive delay | Atraso de 20 segundos em novas operações interativas. |
| 60 min – 24 horas | Interactive rejection | Operações interativas rejeitadas; jobs de background continuam rodando. |
| > 24 horas | Background rejection | Tudo é rejeitado. |
- Operações de Warehouse são classificadas como background, então ganham a janela generosa de smoothing de 24 horas.
- Real-Time Intelligence começa a sofrer throttling já no estágio de 60 minutos — pula completamente o atraso interativo de 20 segundos.
- Eventstreams não rejeitam nada; em vez disso reduzem a alocação de CU.
Como resolver uma capacity com throttling, em ordem de preferência: esperar (capacities se autorrecuperam à medida que o carryforward é consumido) → aumentar temporariamente o SKU → distribuir cargas entre capacities → habilitar overage billing (taxa 3×) → pausar e retomar, o que zera o uso futuro mas deixa o conteúdo indisponível. Diagnostique com o Microsoft Fabric Capacity Metrics app: a tabela de system events na página Compute, a aba Overages e a métrica Minutes to burndown.
OneLake
Um data lake lógico por tenant, provisionado automaticamente, sem infraestrutura para criar. Sua estrutura é fixa e vale desenhar no papel:
- Delta Parquet é o formato nativo de todas as cargas de trabalho. Warehouse, Lakehouse e Eventhouse gravam em Delta, e é isso que permite uma única cópia ser lida por todos os engines.
- O OneLake expõe um subconjunto das APIs do ADLS Gen2 e do Blob, então ferramentas externas o endereçam como
https://onelake.dfs.fabric.microsoft.com/<workspace>/<item>/Tables/<table>. - Uma tenant setting na seção OneLake controla se aplicativos externos (APIs do ADLS, OneLake file explorer) podem acessá-lo. Desligá-la não bloqueia os engines do próprio Fabric.
- Criptografia em repouso usa chaves gerenciadas pela Microsoft por padrão (chaves gerenciadas pelo cliente são opcionais); TLS 1.2 no mínimo em trânsito.
A taxonomia de itens que você precisa reconhecer de imediato
Lakehouse
Tabelas Delta + arquivos não estruturados, Spark em primeiro lugar, com um SQL analytics endpoint somente leitura anexado. Schema-on-read.
Notebook · Spark Job Definition · Environment
Código interativo, código em lote submetido, e a configuração reutilizável de runtime/bibliotecas/computação à qual os outros dois se anexam.
Warehouse
T-SQL completo de leitura e escrita, transações ACID multi-tabela, schema-on-write. É o único store do Fabric com DML de verdade.
Eventstream · Eventhouse · KQL Database
Roteamento de streams sem código; o container das KQL databases; o store de séries temporais consultado com KQL.
Pipeline · Dataflow Gen2 · Copy job
Orquestração + atividades; transformação com Power Query; replicação full/incremental/CDC guiada por assistente, sem pipeline.
Mirrored database · Variable library · Activator
Réplica quase em tempo real de um banco externo; valores de configuração por estágio; o motor de regras por trás de alertas e event triggers.
Escolhendo um data store — a tabela de decisão mestra
Esta única tabela responde a uma fatia desproporcional das questões do Domínio 2.
| Store | Carga ideal | Persona / habilidade | API de escrita | Transações multi-tabela |
|---|---|---|---|---|
| Lakehouse | Big data, ML, dados não e semiestruturados, engenharia de dados | Data engineer, data scientist — Spark | Spark (PySpark, Scala, Spark SQL, R), pipelines, Dataflows | Não |
| Warehouse | DW corporativo, BI baseado em SQL, OLAP, suporte transacional completo | Desenvolvedor de DW, arquiteto de dados, DBA — T-SQL | DML em T-SQL, COPY INTO, CTAS, pipelines | Sim |
| Eventhouse / KQL DB | Streaming, telemetria, logs, análise interativa de alta granularidade sobre JSON/texto | Desenvolvedor de aplicações, data engineer — KQL | Eventstream, SDKs, Kafka, .ingest, Dataflows | Não |
| SQL database no Fabric | OLTP operacional dentro do Fabric | Desenvolvedor de aplicação/banco, DBA — T-SQL | T-SQL (superfície OLTP completa) | Sim |
| Cosmos DB no Fabric | Aplicações de IA, NoSQL, vector search | Desenvolvedor de IA/aplicações — REST/SDK | API REST, SDKs de linguagem | Não |
Portanto a escolha nunca é "qual deles outros engines conseguem ler" — todos conseguem. A escolha é sobre semântica de escrita, a linguagem do desenvolvedor e a latência.
Workspace roles — decore esta matriz
| Capacidade | Admin | Member | Contributor | Viewer |
|---|---|---|---|---|
| Atualizar / excluir o workspace | ✔ | — | — | — |
| Adicionar ou remover pessoas, inclusive outros admins | ✔ | — | — | — |
| Adicionar members e papéis inferiores; permitir recompartilhamento | ✔ | ✔ | — | — |
| Criar workspace identity | ✔ | — | — | — |
| Conectar o workspace a um repositório Git | ✔ | — | — | — |
| Criar / modificar itens de warehouse, database e mirroring | ✔ | ✔ | ✔ | — |
| Escrever, excluir, executar notebooks / pipelines / Spark jobs | ✔ | ✔ | ✔ | — |
Ler dados de Lakehouse e Warehouse via T-SQL (ReadData) | ✔ | ✔ | ✔ | ✔ |
Ler dados via APIs do OneLake e Spark (ReadAll) | ✔ | ✔ | ✔ | — |
| Ler dados do Lakehouse no Lakehouse explorer | ✔ | ✔ | ✔ | — |
| Assinar OneLake events | ✔ | ✔ | ✔ | — |
| Ver a saída de execução de pipelines / notebooks | ✔ | ✔ | ✔ | ✔ |
| Alterar configurações de gateway; agendar refresh via gateway | ✔ | ✔ | ✔ | — |
Um Viewer consegue ler dados de Lakehouse e Warehouse via T-SQL (o SQL analytics endpoint), mas não consegue lê-los via Spark, pelas APIs do OneLake ou pelo Lakehouse explorer. Se alguém precisa consultar com um notebook, Viewer não basta — promova para Contributor ou adicione a pessoa a uma OneLake security role.
Implementar e gerenciar uma solução de análise
Configuração e governança. Quatro grupos de objetivos: workspace settings, gerenciamento de ciclo de vida, segurança e governança, e orquestração. É neste domínio que vivem as questões de "em que ordem você executa estas etapas".
Objetivo 1.1Configurar workspace settings do Microsoft Fabric
Spark workspace settings
Workspace settings → Data Engineering/Science → Spark settings. Quatro abas importam: Pool, Environment, Job admission (High concurrency) e Automatic log.
Starter pools vs. custom pools
| Starter pool | Custom pool | |
|---|---|---|
| Tempo de início | 5–10 segundos (pré-aquecido, gerenciado pela Microsoft, best effort) | 2–5 minutos sob demanda; ~5 s num custom live pool com bibliotecas pré-instaladas |
| Tamanho de nó | Somente Medium | Small → XX-Large |
| Escala | Dinâmica, contra capacidade pré-aquecida | Manual ou autoscale (nós mín./máx.) |
| Cobrança | Só enquanto uma sessão está executando de fato. Inicialização, inicialização de contexto ociosa e desalocação não são cobradas. | |
| Use para | Exploração ad hoc, iteração rápida | Produção, latência previsível, controle de recursos |
Famílias de nós
| Tamanho do nó | vCores | Memória | Máx. de nós numa F64 |
|---|---|---|---|
| Small | 4 | 32 GB | 96 |
| Medium | 8 | 64 GB | 48 |
| Large | 16 | 128 GB | 24 |
| X-Large | 32 | 256 GB | 12 |
| XX-Large | 64 | 512 GB | 6 |
1 Capacity Unit = 2 Spark vCores, e o burst multiplier padrão é 3×.
Então F64 → 64 × 2 = 128 vCores base → 384 vCores com burst. É por isso que um pool de 48 nós Medium (48 × 8 = 384) é o máximo que você consegue definir numa F64. X-Large e XX-Large exigem uma SKU que não seja trial.
- Autoscale — defina nós mínimos e máximos; o decommissioning de executores vem ligado por padrão (
spark.yarn.executor.decommission.enabled = true). - Dynamic executor allocation — reserva executores na submissão a partir do mínimo, pede mais durante a execução e libera ao terminar. Elimina o tuning manual por estágio.
- Expiração de sessão — padrão de 20 minutos; o pool é desalocado 2 minutos depois da expiração. Pools de nó único são suportados (driver e executor no mesmo nó, com recursos pela metade).
- High concurrency — permite que vários notebooks compartilhem uma sessão Spark (e, quando habilitado para pipelines, que atividades de notebook da mesma execução compartilhem a sessão). Reduz drasticamente o custo de inicialização para muitos notebooks pequenos.
Environments
Um Environment é um item do workspace que agrupa três coisas: Spark compute (versão do runtime + propriedades de sessão), bibliotecas (feeds públicos e uploads de .whl/.jar próprios) e resources (arquivos pequenos compartilhados entre os notebooks anexados).
- Save deixa as mudanças em staging; Publish as aplica. Apenas um publish por vez; você não pode editar bibliotecas ou compute durante um publish.
- Quick mode publica em cerca de 5 segundos. Full mode leva de 3 a 6 minutos para publicar mais 1 a 3 minutos na inicialização da sessão, mas produz um snapshot — use-o para pipelines, execuções agendadas e cargas compartilhadas.
- Resources são em tempo real; nunca precisam de publish.
- Anexe em três níveis: padrão do workspace (Workspace settings → Spark settings → aba Environment), notebook ou Spark job definition. Assim que um environment vira o padrão do workspace, só workspace admins podem atualizá-lo.
- Anexar entre workspaces exige a mesma capacity e as mesmas configurações de segurança de rede, e a configuração de compute do environment de origem é ignorada — o pool do workspace atual prevalece.
- Mudanças só valem na próxima sessão.
Domain workspace settings
Domains são agrupamentos lógicos de workspaces por área de negócio — o mecanismo para um modelo de governança federado, tipo data mesh. Subdomains os refinam e herdam os admins do pai.
| Papel | Pode fazer |
|---|---|
| Fabric admin | Criar/renomear/excluir domains, nomear domain admins e contributors, atribuir workspaces, gerenciar todos os domains. |
| Domain admin | Editar a descrição e a imagem, definir contributors, atribuir workspaces, sobrescrever delegated settings. Não pode excluir o domain, mudar o nome dele nem alterar outros admins. |
| Domain contributor | Atribuir os próprios workspaces (precisa ser workspace admin). Sem acesso ao admin portal. |
- Atribua workspaces de três formas: por nome do workspace, por workspace admin (pega todos os workspaces que aquelas pessoas administram) ou por capacity. As duas últimas excluem os "My workspaces" pessoais.
- Default domain — definido para usuários/grupos específicos: os workspaces não atribuídos deles passam a ser atribuídos, novos workspaces são atribuídos automaticamente e essas pessoas viram domain contributors.
- Delegated settings permitem que um domain sobrescreva certas tenant settings — em especial sensitivity labels padrão e certification (habilitar/desabilitar, nomear os certificadores, informar uma URL de documentação).
Atribuir um workspace a um domain não muda visibilidade, acessibilidade nem permissões dos itens. Muda a filtragem no OneLake catalog e habilita configurações de governança federada. Se uma questão oferecer "atribuir a um domain" como forma de restringir acesso, está errada.
OneLake workspace settings
- Shortcut cache — On/Off, um período de retenção de 1 a 28 dias e um botão Reset cache. O contador de retenção reinicia a cada acesso ao arquivo. Arquivos maiores que 1 GB não são cacheados. O cache vale para shortcuts de GCS, Amazon S3, compatíveis com S3 e via on-premises gateway — é uma otimização de custo de egresso entre nuvens.
- Workspace identity — uma managed identity do workspace (criada só por um Admin). É o pré-requisito para trusted workspace access a contas ADLS Gen2 atrás de firewall e para managed private endpoints.
- Managed private endpoints — conectividade privada do Spark do Fabric a fontes de dados atrás de uma VNet.
Apache Airflow job workspace settings
Apache Airflow job é o sucessor do Workflow Orchestration Manager do ADF: um serviço gerenciado de Airflow para orquestração code-first com DAGs em Python.
- Airflow 2.10.5 sobre Python 3.12. Não dá para mudar a versão do Airflow de um job existente — crie um novo.
- Suporta Git sync para armazenar DAGs, Azure Key Vault como backend de segredos, pacotes privados, autoscaling, alta disponibilidade, deferrable operators e pause/resume TTL.
- Redes privadas/virtuais não são suportadas.
- Escolha Airflow em vez de um pipeline quando a equipe já escreve DAGs de Airflow, precisa de ramificação ou geração dinâmica de tarefas em Python, ou está migrando DAGs existentes. Escolha um pipeline do Fabric para orquestração sem código.
Objetivo 1.2Implementar gerenciamento de ciclo de vida no Fabric
Configurar controle de versão (Git integration)
A Git integration é configurada no nível do workspace e liga um workspace a um branch e uma pasta. Provedores suportados: Azure DevOps, GitHub e GitHub Enterprise — apenas na nuvem. Somente um Admin do workspace pode conectá-lo a um repositório.
Tipos de item suportados (lista parcial — saiba o formato geral, não cada entrada): Lakehouse, Notebook, Spark Job Definition, Environment, GraphQL, User Data Functions, Copy Job, Dataflow Gen2, Pipeline, Mirrored Database, Warehouse, Mirrored Azure Databricks Catalog, Eventhouse, Eventstream, KQL Database, KQL Queryset, Real-Time Dashboard, Activator, SQL database, Variable Library. Vários itens de Power BI e Data Science ainda estão em Preview.
Se o workspace contém tipos de item que o Git não suporta, você ainda consegue conectar. Esses itens são ignorados — nunca salvos, nunca sincronizados, nunca excluídos — mas aparecem no painel de source control e você não consegue fazer commit nem update deles. Reports ligados a modelos semânticos do Azure AS / SSAS, push datasets, live connections e modelos semânticos Model v1 não são suportados.
Estados do Git
- Synced — idêntico no workspace e no branch.
- Uncommitted — alterado só no workspace. Faça commit.
- Modified / Update required — alterado só no branch. Faça update.
- Conflict — alterado nos dois. Resolva escolhendo a versão do workspace ou a do branch, item a item.
Database projects
Para Warehouses, é o controle de versão do schema em si. Use a extensão SQL Database Projects no VS Code (ou Azure Data Studio) para extrair o warehouse num .sqlproj, comparar com outro ambiente usando Schema Compare e publicar com o SqlPackage. É a resposta quando o requisito é "implantar apenas as mudanças de schema como parte de um release pipeline de DevOps existente", em vez de "promover itens inteiros".
Deployment pipelines
O mecanismo nativo de promoção de conteúdo do Fabric: de 2 a 10 estágios (padrão 3 — Development, Test, Production), cada estágio com um workspace atribuído.
| Conceito | Comportamento |
|---|---|
| Pairing | Itens são pareados entre estágios adjacentes e continuam pareados mesmo se renomeados. O pareamento acontece ao atribuir um workspace a um estágio, ou ao implantar conteúdo ainda não pareado. |
| Duplicatas não pareadas | Dois itens com o mesmo nome e tipo em workspaces adjacentes que nunca foram pareados vão criar duplicatas na implantação, não sobrescrever. Essa é a pegadinha clássica. |
| Deployment rules | Sobrescritas por estágio para fontes de dados e parâmetros, para que o Test aponte para o lakehouse de Test. |
| Não é copiado | Permissões e configurações de compartilhamento nunca são copiadas adiante. Alguns agendamentos de refresh também não. |
| Automação | APIs REST de Deployment Pipelines, além do Fabric CLI e do provider do Terraform para CI/CD completo. |
| Permissão | Workspace admin, para criar pipelines, atribuir workspaces, implantar e definir regras. |
| Git integration | Deployment pipelines | |
|---|---|---|
| Propósito | Histórico de versões, branching, code review, backup | Promover conteúdo Dev → Test → Prod |
| Unidade de trabalho | Um commit num branch | Uma implantação entre estágios adjacentes |
| Gatilho | Commit / update, fluxo de PR | Botão manual ou API REST |
Uma configuração madura usa os dois: Git no workspace de desenvolvimento e para code review, deployment pipelines (ou as APIs) para promoção.
Variable libraries
Um item do workspace que guarda variáveis de configuração mais value sets alternativos — um por estágio do ciclo de vida — com exatamente um value set ativo por vez. Os consumidores resolvem o valor a partir do conjunto ativo no próprio workspace, então a mesma definição de pipeline aponta para o lakehouse de dev em Dev e para o de prod em Prod, sem precisar de deployment rule.
- Tipos: string, integer, boolean e referências a itens.
- Consumidores: Pipeline, shortcut de Lakehouse, Notebook (via
notebookutils.variableLibrarye%%configure), Dataflow Gen2, Copy job, User data functions, Plan. - Limites: até 1.000 variáveis e 1.000 value sets; menos de 10.000 células no total; item ≤ 1 MB; notas e descrições ≤ 2.048 caracteres.
- Não dá para excluir o value set ativo — ative outro antes.
- Funciona tanto com Git integration quanto com deployment pipelines, e é exposto pelas APIs públicas do Fabric.
Objetivo 1.3Configurar segurança e governança
As quatro camadas de controle de acesso do Fabric
Controles de acesso no nível do item
| Permissão | Concede | Efeito em Lakehouse / Warehouse |
|---|---|---|
Read | Ver o item e seus metadados; conectar ao SQL analytics endpoint | Só metadados — nenhum dado sem uma concessão adicional |
ReadData | Consultar dados via T-SQL | Acesso pelo SQL endpoint (modo delegated identity) |
ReadAll | Ler os arquivos subjacentes | Acesso via OneLake / Spark / Lakehouse explorer; corresponde à role DefaultReader do OneLake |
Write | Modificar o item | Acesso completo a metadados + SQL + OneLake |
Execute | Executar o item | Notebooks, pipelines, Spark job definitions |
Build | Construir conteúdo novo sobre um modelo semântico | Necessário para criar relatórios Direct Lake |
Reshare | Repassar a concessão | — |
OneLake security (roles no plano de dados)
Uma OneLake security role tem quatro partes: dados (as tabelas ou pastas que ela cobre), permissões, membros e restrições (exclusões de linhas e colunas). As roles são definidas uma vez e aplicadas por todos os engines do Fabric — e por "authorized engines" externos registrados, que buscam a política efetiva pelas APIs do OneLake.
- Somente workspace Admin ou Member pode criar OneLake security roles.
- Elas governam Viewers e usuários com permissão de item
Read/ReadData. Workspace Admins, Members e Contributors as ignoram completamente — sempre leem e escrevem tudo. - Todo lakehouse já vem com uma role DefaultReader que concede acesso a quem tem
ReadAll. Ela pode ser editada ou excluída. - Segurança em nível de pasta no lakehouse de origem também governa os shortcuts que apontam para ele — a segurança acompanha o dado, não a referência.
- Subpastas herdam as permissões do pai por padrão.
Se a pessoa é Contributor do workspace, nenhuma OneLake role vai restringi-la. A sequência correta é: remover a pessoa do workspace role, conceder Read no nível do item e então adicioná-la a uma OneLake security role com escopo naquela pasta.
Segurança de linha, coluna e objeto no Warehouse
Row-level security
Uma função de predicado inline table-valued mais uma security policy. RLS funciona tanto no Warehouse quanto no SQL analytics endpoint.
-- 1. A função de predicado: retorna uma linha quando o acesso é permitido CREATE FUNCTION Security.tvf_SecurityPredicate(@SalesRep AS nvarchar(50)) RETURNS TABLE WITH SCHEMABINDING AS RETURN SELECT 1 AS result WHERE @SalesRep = USER_NAME() OR USER_NAME() = 'gerente@contoso.com'; GO -- 2. Vincule à tabela CREATE SECURITY POLICY Security.SalesFilter ADD FILTER PREDICATE Security.tvf_SecurityPredicate(SalesRep) ON dbo.Sales WITH (STATE = ON); GO
ADD FILTER PREDICATE esconde linhas silenciosamente nas leituras. ADD BLOCK PREDICATE ... AFTER INSERT | AFTER UPDATE | BEFORE UPDATE | BEFORE DELETE lança erro em escritas que violariam a regra. Se uma questão pergunta como impedir um usuário de gravar uma linha fora da região dele, a resposta é block predicate.
Column-level security
GRANT SELECT ON dbo.Employees(EmployeeId, FirstName, LastName, Department) TO [analistas@contoso.com]; -- ou negue colunas específicas numa tabela já concedida DENY SELECT ON dbo.Employees(Salary, NationalId) TO [analistas@contoso.com];
Object-level security
CREATE ROLE SalesAnalyst; GRANT SELECT ON SCHEMA::sales TO SalesAnalyst; DENY SELECT ON dbo.PayrollDetail TO SalesAnalyst; ALTER ROLE SalesAnalyst ADD MEMBER [usuario@contoso.com];
Dynamic data masking
Mascara valores apenas no resultado da consulta — o dado armazenado não muda. Usuários com a permissão UNMASK (e workspace Admin/Member/Contributor) veem os valores reais.
| Função | Sintaxe | Resultado |
|---|---|---|
| Default | default() | XXXX para strings, 0 para numéricos, 1900-01-01 para datas |
email() | aXXX@XXXX.com | |
| Random | random(1, 100) | Um número aleatório no intervalo — somente tipos numéricos |
| Partial | partial(0,"XXXX-",4) | Preserva um prefixo e um sufixo, preenche o meio |
| Datetime | datetime("M") | Mascara tudo, exceto a parte da data escolhida |
ALTER TABLE dbo.Customers ALTER COLUMN Email ADD MASKED WITH (FUNCTION = 'email()'); ALTER TABLE dbo.Payments ALTER COLUMN CardNumber ADD MASKED WITH (FUNCTION = 'partial(0,"XXXX-XXXX-XXXX-",4)'); GRANT UNMASK TO [financeiro-admin@contoso.com]; ALTER TABLE dbo.Customers ALTER COLUMN Email DROP MASKED; -- remover
Quem pode consultar a tabela ainda consegue inferir valores mascarados com WHERE Salary > 100000. DDM complementa RLS/CLS; nunca substitui.
Sensitivity labels e endorsement
- Sensitivity labels vêm do Microsoft Purview Information Protection. São aplicados por item, propagam-se para baixo pela linhagem (um relatório herda do seu modelo semântico) e podem carregar criptografia que acompanha os arquivos exportados. Aplicá-los exige que o label esteja publicado para o usuário e a tenant setting habilitada. Um domain pode definir um label padrão via delegated settings.
- Endorsement tem três níveis:
- Promoted — qualquer usuário com permissão de escrita no item pode promover.
- Certified — somente usuários nomeados como certificadores pelo Fabric admin (ou pelo domain admin, via delegated settings) podem certificar.
- Master data — a fonte autoritativa para uma área de assunto.
Fabric audit logs
- A atividade do Fabric flui para o unified audit log do Microsoft Purview / Microsoft 365. Acesse pelo portal de compliance do Purview, pelo link Audit logs no admin portal do Fabric, ou programaticamente com
Get-PowerBIActivityEvent/ a API REST Admin Activity Events. - O admin monitoring workspace traz o relatório Feature usage and adoption e um modelo semântico de dados de atividade para Fabric admins.
- Workspace monitoring (workspace settings → Monitoring → Log workspace activity) provisiona um Eventhouse somente leitura no workspace que coleta logs de diagnóstico e métricas de Eventhouse, Eventstream, pipelines, Copy jobs, mirrored databases, GraphQL e modelos semânticos. A retenção é de 30 dias; é cobrado como consumo normal de capacity de Eventhouse/Eventstream; você pode habilitar workspace monitoring ou Log Analytics, não os dois. Consulte com KQL ou SQL.
- Operações de plano de dados do OneLake aparecem com nomes que correspondem às APIs do ADLS Gen2 (
CreateFile,DeleteFile…). Requisições de leitura e requisições das cargas de trabalho do Fabric não são incluídas.
Objetivo 1.4Orquestrar processos
Escolher entre Dataflow Gen2, pipeline e notebook
| Copy activity (pipeline) | Copy job | Dataflow Gen2 | Notebook / Spark | Eventstream | |
|---|---|---|---|---|---|
| Caso de uso | Migração de lake/DW, ingestão, transformação leve | Ingestão, cópia incremental, replicação | Ingerir, transformar, limpar, perfilar | Ingerir, transformar, processar, perfilar | Ingestão e transformação de eventos |
| Persona | Data engineer / integrador | Analista, integrador, engenheiro | Engenheiro, integrador, analista | Data engineer, integrador | Engenheiro, cientista, desenvolvedor |
| Habilidades | ETL, SQL, JSON | ETL, SQL, JSON | ETL, M, SQL | Spark (Python, Scala, SQL, R) | SQL, JSON, mensageria |
| Código | Sem/baixo código | Sem/baixo código | Sem/baixo código | Com código | Sem código |
| Fontes | 50+ conectores | 50+ conectores | 150+ conectores | Centenas de bibliotecas Spark | CDC, Kafka, mensageria, streams |
| Complexidade de transformação | Baixa | Baixa | Baixa → alta (300+ funções) | Baixa → alta (ilimitada) | Baixa |
| Interface | Assistente, canvas | Assistente, canvas | Power Query | Notebook, Spark job definition | Canvas |
- O cenário diz "Power Query", "o analista sabe M" ou "150+ conectores" → Dataflow Gen2.
- O cenário diz "petabyte", "lógica complexa/customizada", "ML", "não estruturado" → notebook.
- O cenário diz "CDC", "sem precisar de pipeline", "poucos cliques", "retomar de onde parou" → Copy job.
- O cenário diz "orquestrar", "em caso de falha", "iterar sobre", "depois atualizar o modelo" → pipeline.
- O cenário diz "sem agendamento", "à medida que os eventos chegam" → Eventstream.
Atividades de pipeline que você precisa reconhecer
Mover e transformar
Copy data · Copy job · Dataflow Gen2 · Notebook · Spark Job Definition · Script · Stored procedure · Lakehouse maintenance Preview
Controle de fluxo
ForEach · If Condition · Switch · Until · Wait · Set variable · Filter · Invoke pipeline · Fail
Lookup e metadados
Lookup · Get Metadata · Web · Web hook · Azure Function
Notificação
Office 365 Outlook · Teams · Semantic model refresh · KQL activity
Toda atividade suporta quatro condições de dependência na seta de saída: On success, On failure, On completion e On skip. As atividades também expõem Retry, Retry interval, Timeout e Secure output/input na aba General.
Parâmetros e expressões dinâmicas
Parâmetros são definidos uma vez por execução e são somente leitura dentro dela. Variáveis são mutáveis durante a execução, via as atividades Set variable e Append variable.
| Expressão | Retorna |
|---|---|
@pipeline().PipelineName / .Pipeline | Nome / ID do pipeline |
@pipeline().RunId | ID desta execução — a chave de correlação padrão para logging |
@pipeline().TriggerTime, .TriggerName, .TriggerId | Metadados do trigger, em UTC ISO 8601 |
@pipeline().DataFactory | ID do workspace |
@pipeline()?.TriggeredByPipelineName | Nome do pipeline pai, ou null |
@pipeline().parameters.<nome> / @variables('nome') | Valor do parâmetro / variável |
@activity('Lookup1').output.firstRow.WatermarkValue | Um campo da saída de uma atividade anterior |
@activity('Copy1').error.message | Mensagem de falha, para logar no caminho de erro |
@item() | O elemento atual dentro de um ForEach |
@pipeline()?.TriggerEvent?.FileName | Nome do arquivo vindo de um storage event trigger (? protege contra null em execuções manuais) |
// Interpolação de string usa @{ }; um @ sozinho inicia uma expressão; @@ escapa um @ literal "Test_@{formatDateTime(utcNow(), 'yyyy-MM-dd')}" // Funções comuns por categoria Data/hora : addDays addHours addMinutes formatDateTime utcNow startOfDay ticks convertFromUtc String : concat replace split substring startsWith endsWith toLower trim indexOf guid Coleção : contains empty first last length skip take union join intersection Lógica : and or not if equals greater greaterOrEquals less lessOrEquals Conversão : array bool float int string json coalesce createArray base64 uriComponent Matemática: add sub mul div mod min max rand range // Exemplos práticos @concat('vendas_', formatDateTime(utcNow(), 'yyyyMMdd'), '.parquet') @if(greater(activity('Lookup_RowCount').output.firstRow.cnt, 0), 'load', 'skip') @formatDateTime(addDays(utcNow(), -1), 'yyyy-MM-ddTHH:mm:ssZ') @coalesce(pipeline().parameters.RunDate, formatDateTime(utcNow(), 'yyyy-MM-dd'))
Passando parâmetros para um notebook
# No notebook CHAMADO: marque uma célula como "parameter cell" (no menu da célula) # e declare os padrões ali. Os valores do chamador sobrescrevem em tempo de execução. run_date = "2026-01-01" layer = "bronze" # Devolver um valor ao chamador import notebookutils notebookutils.notebook.exit(str(rows_written)) # No notebook CHAMADOR exit_val = notebookutils.notebook.run("Load_Bronze", 90, {"run_date": "2026-08-30", "layer": "silver"}) # 4º argumento posicional = ID do workspace, para chamadas entre workspaces (Runtime 1.2+)
A partir de um pipeline, os Base parameters da atividade Notebook mapeiam para a mesma parameter cell, e o valor de exit() do notebook é lido adiante como @activity('Notebook1').output.result.exitValue.
Orquestrando muitos notebooks com um DAG
DAG = {
"activities": [
{"name": "LoadCustomers", "path": "nb_load_customers",
"timeoutPerCellInSeconds": 120, "args": {"layer": "bronze"}},
{"name": "LoadOrders", "path": "nb_load_orders",
"timeoutPerCellInSeconds": 120, "args": {"layer": "bronze"}},
{"name": "BuildFactSales", "path": "nb_build_fact",
"timeoutPerCellInSeconds": 300,
"retry": 1, "retryIntervalInSeconds": 30,
"dependencies": ["LoadCustomers", "LoadOrders"]}
],
"timeoutInSeconds": 43200, # 12 h, o padrão
"concurrency": 50 # 0 = sem limite
}
notebookutils.notebook.runMultiple(DAG, {"displayDAGViaGraphviz": True})
# Forma paralela simples, sem dependências:
notebookutils.notebook.runMultiple(["nb_a", "nb_b", "nb_c"])O runMultiple executa todos os notebooks filhos numa única sessão Spark — sem inicialização de sessão por notebook, então dez notebooks pequenos terminam numa fração do tempo e do CU. Use um pipeline quando precisar de tipos de atividade variados, orquestração entre itens, retries no nível do item ou event triggers.
Agendamentos e event-based triggers
| Mecanismo | Como funciona | Observações |
|---|---|---|
| Sob demanda | Run no editor | Os trigger parameters resolvem para null — por isso as proteções com ? importam |
| Agendamento fixo | Home → Schedule. Frequência, data de início e fim, fuso horário | Data de início e fim são obrigatórias; use uma data de fim bem distante. Até 20 agendamentos por pipeline |
| Agendamento por intervalo Preview | Intervalos fixos e não sobrepostos | Expõe Window start time / Window end time como trigger parameters — a forma limpa de fazer cargas em lote com janela tumbling |
| Storage event trigger | Home → Trigger → cria um Eventstream + um item Activator (Reflex) | Fontes: OneLake events, Azure Blob Storage events. Filtre pelo campo Subject (pasta, nome do arquivo, extensão, container) |
| Fabric item / job events | Item do workspace criado/atualizado/excluído; job events | Tipos de evento como Microsoft.Fabric.ItemCreateSucceeded, …ItemUpdateFailed |
Os payloads de storage event seguem o schema CloudEvents: source, subject, type (por exemplo Microsoft.Storage.BlobCreated), time, id, data, specversion. O Fabric extrai nome do arquivo e caminho da pasta do Subject e os expõe no expression builder como trigger parameters.
Um event trigger criado a partir de um pipeline é armazenado como um item Activator (Reflex) separado no workspace, não dentro do pipeline. Para encontrá-lo, editá-lo ou desativá-lo, abra esse item Reflex ou use Triggers → View triggers no pipeline. Excluir o pipeline não exclui o trigger.
Padrões de orquestração que vale conhecer pelo nome
Ingestão orientada a metadados
Uma tabela de controle lista fontes, destinos, watermarks e tipo de carga. Um Lookup a lê, um ForEach itera sobre @activity('Lookup').output.value, e uma única Copy activity parametrizada atende todas as fontes. Desligue Sequential e ajuste o Batch count (máx. 50) para paralelismo.
Orquestração medallion
Bronze (bruto, append-only) → Silver (limpo, deduplicado, conformado) → Gold (star schema, agregado). Um pipeline por camada, encadeados com Invoke pipeline, para que cada camada possa ser reexecutada independentemente.
Loop de watermark
Lookup do watermark antigo → Copy das linhas > watermark → Lookup do novo máximo → Stored procedure grava o novo watermark. Atualize o watermark somente em caso de sucesso, para que uma falha reprocesse em vez de pular dados.
Reexecuções idempotentes
Projete de forma que reexecutar não duplique: MERGE em vez de INSERT, sobrescrita de partição com replaceWhere em vez de append, e uma chave de negócio determinística. Cenários de prova adoram "o pipeline foi reexecutado após uma falha e as linhas duplicaram".
Ingerir e transformar dados
O domínio mais prático. Padrões de carga e modelagem dimensional, ingestão e transformação em lote com PySpark / T-SQL / KQL, e streaming com Eventstream, Eventhouse e Spark Structured Streaming.
Objetivo 2.1Projetar e implementar padrões de carga
Cargas full e incremental
| Padrão | Quando | Implementação no Fabric |
|---|---|---|
| Carga full / truncate-and-reload | Tabelas pequenas, sem marcador de mudança confiável, reconstrução de dimensões cujas surrogate keys não são referenciadas | TRUNCATE TABLE + INSERT…SELECT, CTAS, ou mode("overwrite") no Spark |
| Watermark / high-water mark | A origem tem uma coluna monotonicamente crescente (ROWVERSION, datetime, identity) | Lookup + Copy parametrizado; ou Copy job em modo incremental. Captura apenas inserts e updates |
| CDC | Você precisa capturar deletes, ou a origem muda muito | Copy job em modo CDC, fontes CDC do Eventstream, ou Mirroring |
| Sobrescrita de partição | Recarregar uma fatia delimitada, por exemplo o dia anterior | replaceWhere do Delta, ou dynamic partition overwrite |
| Upsert / merge | Correções tardias numa tabela existente | MERGE do Delta no Spark, MERGE em T-SQL no Warehouse |
from delta.tables import DeltaTable from pyspark.sql import functions as F # 1. Ler o watermark atual do destino watermark = spark.sql("SELECT COALESCE(MAX(ModifiedDate), '1900-01-01') AS wm FROM silver.customers") \ .collect()[0]["wm"] # 2. Trazer apenas linhas novas/alteradas src = (spark.read.format("delta").load("Tables/bronze/customers") .filter(F.col("ModifiedDate") > F.lit(watermark))) # 3. UPSERT com MERGE tgt = DeltaTable.forName(spark, "silver.customers") (tgt.alias("t") .merge(src.alias("s"), "t.CustomerId = s.CustomerId") .whenMatchedUpdateAll(condition="s.ModifiedDate > t.ModifiedDate") .whenNotMatchedInsertAll() .whenNotMatchedBySourceUpdate(set={"IsDeleted": "true"}) # soft delete .execute()) # 4. Alternativa: sobrescrita idempotente de uma fatia delimitada (df.write.format("delta").mode("overwrite") .option("replaceWhere", "LoadDate >= '2026-08-01' AND LoadDate < '2026-09-01'") .saveAsTable("silver.orders"))
Preparando dados para um modelo dimensional
A orientação do Fabric é o Kimball clássico: um star schema com tabelas fato cercadas por tabelas dimensão. Fatos guardam medidas mais as chaves de dimensão, num grão declarado; dimensões descrevem as entidades.
PRIMARY KEY, UNIQUE e FOREIGN KEY só podem ser criadas com a opção NOT ENFORCED. São metadados usados pelo otimizador de consultas e por ferramentas de modelagem — o engine deixa você inserir uma chave duplicada ou uma linha de fato órfã sem reclamar. Seu ETL precisa garantir unicidade e integridade referencial por conta própria.
Slowly changing dimensions
| Tipo | Comportamento | Implementação |
|---|---|---|
| Tipo 0 | Nunca muda (ex.: data original de cadastro) | Apenas insert |
| Tipo 1 | Sobrescreve — sem histórico | MERGE … WHEN MATCHED THEN UPDATE |
| Tipo 2 | Nova linha a cada mudança, com StartDate/EndDate/IsCurrent | Expira a linha atual e insere a nova versão |
| Tipo 3 | Guarda um valor anterior numa coluna extra | PreviousValue = Value e depois atualiza Value |
| Tipo 6 | Híbrido 1+2+3 | Linhas Tipo 2 mais uma coluna de "valor atual" atualizada em todas as linhas |
-- Etapa 1: expirar linhas cujos atributos monitorados mudaram UPDATE d SET d.EndDate = CAST(GETDATE() AS date), d.IsCurrent = 0 FROM dbo.DimProduct AS d JOIN staging.Products AS s ON s.ProductID = d.ProductID WHERE d.IsCurrent = 1 AND (d.ProductName <> s.ProductName OR d.Category <> s.Category); -- Etapa 2: inserir a nova versão vigente (e os membros totalmente novos) INSERT INTO dbo.DimProduct (ProductID, ProductName, Category, StartDate, EndDate, IsCurrent, IsInferred) SELECT s.ProductID, s.ProductName, s.Category, CAST(GETDATE() AS date), NULL, 1, 0 FROM staging.Products AS s LEFT JOIN dbo.DimProduct AS d ON d.ProductID = s.ProductID AND d.IsCurrent = 1 WHERE d.ProductID IS NULL; -- Etapa 3: soft delete dos membros que sumiram da origem UPDATE dbo.DimProduct SET IsDeleted = 1, IsCurrent = 0, EndDate = CAST(GETDATE() AS date) WHERE IsCurrent = 1 AND NOT EXISTS (SELECT 1 FROM staging.Products s WHERE s.ProductID = DimProduct.ProductID);
INSERT INTO dbo.FactSales (DateKey, CustomerKey, ProductKey, Quantity, SalesAmount, SourceOrderNumber) SELECT CONVERT(int, FORMAT(o.OrderDate, 'yyyyMMdd')), ISNULL(c.CustomerKey, -1), -- -1 = o membro "Unknown" ISNULL(p.ProductKey, -1), l.Quantity, l.Quantity * l.UnitPrice, o.SalesOrderNumber FROM staging.SalesOrders o JOIN staging.SalesOrderLines l ON l.SalesOrderID = o.SalesOrderID -- join point-in-time: pega a versão da dimensão válida na data do pedido LEFT JOIN dbo.DimCustomer c ON c.CustomerID = o.CustomerID AND o.OrderDate >= c.StartDate AND (o.OrderDate < c.EndDate OR c.EndDate IS NULL) LEFT JOIN dbo.DimProduct p ON p.ProductID = l.ProductID AND p.IsCurrent = 1 WHERE o.SalesOrderNumber > @LastLoadedOrderNumber; -- high-water mark
Regras que o exame cobra sobre carga dimensional
- Nunca faça truncate-and-reload numa dimensão cujas surrogate keys são referenciadas por fatos — você deixaria todas as linhas de fato órfãs.
- Soft delete, nunca hard delete, de membros de dimensão. Fatos históricos ainda apontam para eles.
- Membros inferidos (ou fatos que chegam cedo demais): quando um fato referencia uma chave de dimensão desconhecida, insira uma linha placeholder marcada com
IsInferred = 1e enriqueça-a quando o registro real chegar. - A dimensão de data não tem sistema de origem — gere-a com uma CTE recursiva ou uma tabela de números, bem além da data atual.
- Carregue dimensões antes dos fatos, sempre. Os fatos precisam das chaves.
- Prefira tabelas de staging num schema
stagingpróprio, limpas comTRUNCATE TABLEno início de cada execução.
Um padrão de carga para dados de streaming
Dados de streaming que chegam ao repouso seguem o formato medallion com um ajuste — a camada bronze é append-only e nunca é alterada:
Lakehouse ou Eventhouse para a landing zone? Eventhouse quando as consultas são de séries temporais e interativas e a latência é medida em segundos; Lakehouse quando o stream alimenta os mesmos pipelines em lote de todo o resto. Dá para ter os dois barato: aterrisse no Eventhouse e ligue o OneLake availability, que materializa uma cópia Delta legível pelo Spark e pelo SQL endpoint sem custo extra de armazenamento.
Objetivo 2.2Ingerir e transformar dados em lote
OneLake shortcuts
Um shortcut é um ponteiro que aparece como uma pasta. Nenhum dado é copiado e nenhum armazenamento é consumido.
Shortcuts internos
Apontam para outro item do Fabric: Lakehouse, Warehouse, KQL database, Mirrored database, Mirrored Azure Databricks catalog, SQL database, modelo semântico. A autorização usa a identidade de quem chama — a pessoa precisa de permissão de leitura no destino.
Shortcuts externos
Amazon S3 · compatível com S3 · ADLS Gen2 · Azure Blob Storage · Google Cloud Storage · Dataverse · Iceberg · OneDrive/SharePoint. A autorização é delegada por uma cloud connection, então só quem tem permissão nessa conexão consegue criar o shortcut.
Tables/ | Files/ | |
|---|---|---|
| Aninhamento | Só no nível superior — sem subdiretórios | Qualquer profundidade |
| Descoberta | Metadados e schema Delta sincronizam automaticamente; a tabela aparece no SQL endpoint | Sem descoberta de tabelas |
| Use para | Datasets Delta estruturados, fontes internas do OneLake, schema shortcuts | Dados não e semiestruturados, qualquer formato, stores externos |
# Spark — um shortcut em Tables/ se comporta exatamente como uma tabela nativa df = spark.read.format("delta").load("Tables/MyShortcut") df = spark.sql("SELECT * FROM MyLakehouse.MyShortcut LIMIT 1000") -- SQL analytics endpoint SELECT TOP (100) * FROM [MyLakehouse].[dbo].[MyShortcut]; // KQL — um shortcut numa KQL database é uma external table external_table('MyShortcut') | take 100
- Até 100.000 shortcuts por item; até 10 shortcuts por caminho do OneLake; o encadeamento é limitado a 5 níveis de profundidade.
- Nomes não podem conter
%nem+, e caracteres não latinos não são suportados. Delta não suporta nomes de tabela com espaços — um shortcut com espaço no nome não será reconhecido como tabela Delta. - Excluir um shortcut remove apenas o ponteiro. Mas excluir conteúdo dentro de um shortcut exclui na origem se você tiver permissão lá.
- A visualização de linhagem tem escopo de um workspace e não mostra shortcuts externos.
- Pode levar até um minuto para a Table API reconhecer um shortcut novo.
- Schema shortcuts só funcionam em lakehouses com schema habilitado.
Mirroring
O mirroring replica continuamente um banco operacional externo para o OneLake como tabelas Delta, sem ETL para construir. A computação de replicação é gratuita e cada capacity unit inclui 1 TB de armazenamento de mirroring gratuito (então F64 → 64 TB). A latência pode chegar a ~15 segundos.
| Modalidade | O que replica | Fontes |
|---|---|---|
| Database mirroring | Dados e metadados, gravados como Delta no OneLake | Azure SQL DB, Azure SQL MI, SQL Server, Azure Cosmos DB, Azure Database for PostgreSQL, Snowflake, Oracle, Google BigQuery, SAP Datasphere, Fabric SQL DB; MySQL e SharePoint list em Preview |
| Metadata mirroring | Só a estrutura de catálogo — os dados ficam onde estão e são acessados por shortcuts | Azure Databricks Unity Catalog; Dremio Preview |
| Open mirroring | Você envia os dados de mudança para uma landing zone no OneLake via API pública | Qualquer aplicação própria ou de ISV |
- Cria duas coisas no workspace: o processo de replicação e um SQL analytics endpoint somente leitura.
- Exige uma capacity do Fabric em execução — pausar a capacity interrompe a replicação.
- A retenção Delta é de 1 dia por padrão para bancos criados após meados de junho de 2025 (7 dias para os mais antigos); configurável em Settings → Delta table management ou via
retentionInDaysna API.
- Mirroring — um banco operacional que você quer disponível de forma contínua e barata para análise, em Delta, quase em tempo real.
- Shortcut — dados que já estão num lake (OneLake, ADLS, S3, GCS) e que você não quer duplicar.
- Copy activity / Copy job — movimentação em lote agendada, ou qualquer caso em que você precise de transformação, filtragem ou gateway.
Ingerindo com pipelines e Copy job
Copy activity
- Mais de 50 conectores de origem e 40 de destino; suporta staging (um salto intermediário em blob/lakehouse) para origens que não conseguem enviar direto ao destino.
- Degree of copy parallelism, tolerância a falhas (pular linhas incompatíveis e registrá-las) e copy behavior (preservar hierarquia, achatar hierarquia, mesclar arquivos).
- Conectividade a ambientes on-premises pelo on-premises data gateway, e a uma VNet pelo VNet data gateway.
- Métricas de saída disponíveis adiante:
rowsRead,rowsCopied,rowsSkipped,throughput,dataConsistencyVerification.
Copy job
Um item independente — sem precisar de pipeline — para cópia full, incremental e replicação por CDC.
| Incremental por watermark | Baseado em CDC | |
|---|---|---|
| Captura | Inserts e updates | Inserts, updates e deletes |
| Precisa de | Uma coluna incremental confiável: ROWVERSION, datetime, date, string interpretada como datetime, inteiro | CDC habilitado na origem e suportado pelo conector |
| Permite destino SCD2 | Não | Sim |
Métodos de atualização no destino: Append (padrão), Merge (exige coluna-chave; com CDC também aplica deletes), Overwrite e SCD Tipo 2 com effective dating. O Copy job também grava colunas de auditoria opcionais por linha — hora de extração, caminho do arquivo de origem, IDs de workspace/job/run e os limites da janela incremental — que é a resposta nativa para questões de linhagem em nível de linha. Ele retoma do último checkpoint bem-sucedido após uma falha, suporta Git/CI-CD e Variable libraries, e tem um modo de auto-partitioning em Preview para leituras paralelas de tabelas grandes.
Transformando com PySpark, SQL e KQL
from pyspark.sql import functions as F, Window # Leitura / escrita df = spark.read.format("delta").load("Tables/bronze/orders") df = spark.read.option("header",True).option("inferSchema",True).csv("Files/raw/*.csv") df.write.format("delta").mode("append").saveAsTable("silver.orders") # Formato df2 = (df.withColumn("OrderYear", F.year("OrderDate")) .withColumn("Net", F.col("Gross") - F.col("Discount")) .withColumnRenamed("cust_id", "CustomerId") .drop("_ingest_raw") .filter(F.col("Status") != "Cancelled")) # Agrupar e agregar agg = (df2.groupBy("CustomerId", "OrderYear") .agg(F.sum("Net").alias("Revenue"), F.countDistinct("OrderId").alias("Orders"), F.max("OrderDate").alias("LastOrder"))) # Desnormalizar — faça broadcast do lado pequeno para evitar shuffle wide = df2.join(F.broadcast(dim_customer), "CustomerId", "left") # Window functions: manter a linha mais recente por chave w = Window.partitionBy("CustomerId").orderBy(F.col("ModifiedDate").desc()) latest = df2.withColumn("rn", F.row_number().over(w)).filter("rn = 1").drop("rn") # Semiestruturado flat = (df.withColumn("j", F.from_json("payload", schema)) .select("j.*") .withColumn("tag", F.explode("tags"))) pivoted = df2.groupBy("CustomerId").pivot("OrderYear").sum("Net")
# %%pyspark %%sql %%scala %%sparkr %%html %%configure %%sql CREATE OR REPLACE TABLE silver.customers AS SELECT CustomerId, INITCAP(Name) AS Name, Country FROM bronze.customers WHERE CustomerId IS NOT NULL; %%configure { "defaultLakehouse": { "name": "lh_silver" }, "conf": { "spark.sql.shuffle.partitions": "200" } }
-- CTAS: a forma mais rápida de materializar um resultado transformado CREATE TABLE gold.SalesByRegion AS SELECT r.RegionName, SUM(f.SalesAmount) AS Revenue, COUNT_BIG(*) AS OrderCount, SUM(f.SalesAmount) / NULLIF(COUNT_BIG(*),0) AS AvgOrder FROM dbo.FactSales f JOIN dbo.DimRegion r ON r.RegionKey = f.RegionKey GROUP BY r.RegionName; -- Window functions SELECT CustomerId, OrderDate, SalesAmount, SUM(SalesAmount) OVER (PARTITION BY CustomerId ORDER BY OrderDate ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningTotal, LAG(SalesAmount) OVER (PARTITION BY CustomerId ORDER BY OrderDate) AS PrevOrder, ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY OrderDate DESC) AS Recency FROM dbo.FactSales; -- Agregação em múltiplos níveis SELECT Country, City, SUM(Revenue) AS Revenue, GROUPING(City) AS IsCityTotal FROM gold.Sales GROUP BY ROLLUP (Country, City); -- também: CUBE, GROUPING SETS -- Cross-warehouse / cross-lakehouse numa consulta só (nome em três partes) INSERT INTO gold.DimProduct SELECT * FROM LakehouseSilver.dbo.products;
Events | where Timestamp > ago(7d) and Level in ("Error", "Critical") | extend Duration = EndTime - StartTime, Region = tostring(parse_json(Properties).region) | project Timestamp, DeviceId, Region, Duration, Message | summarize ErrorCount = count(), Devices = dcount(DeviceId), p95 = percentile(Duration, 95), LastSeen = max(Timestamp) by Region, bin(Timestamp, 1h) | order by Timestamp asc, ErrorCount desc
Dados duplicados, ausentes e atrasados
| Problema | Spark | T-SQL | KQL |
|---|---|---|---|
| Duplicatas exatas | df.dropDuplicates(["OrderId"]) | ROW_NUMBER() + WHERE rn = 1 | summarize arg_max(Timestamp, *) by Id |
| Duplicatas num stream | dropDuplicatesWithinWatermark(["Id"]) | — | summarize take_any(*) by Id |
| Valores ausentes | df.na.fill({"Qty":0}), df.na.drop(subset=[…]) | COALESCE(), ISNULL() | coalesce(), iff(isnull(x), 0, x) |
| Chave de dimensão desconhecida | Left join e depois coalesce(key, lit(-1)) | ISNULL(d.Key, -1) ou inserir um membro inferido | Join leftouter + valor padrão |
| Eventos atrasados | withWatermark("ts","10 minutes") | Reprocessar a partição afetada com MERGE | Políticas de ingestion time; consultar por ingestion_time() |
| Linhas ruins | Direcionar para uma tabela quarantine em vez de falhar o job | TRY_CAST + uma tabela de rejeitados | Update policy com IsTransactional = false |
COPY INTOsuporta CSV, JSONL e Parquet vindos de ADLS Gen2 e Azure Blob Storage; por padrão autentica com a identidade Entra de quem executa.- Mantenha os arquivos de origem com ao menos 4 MB (a orientação de performance da Microsoft mira 100 MB – 1 GB por arquivo) e use muitos arquivos em paralelo.
- ADLS Gen2 tem desempenho melhor que o Blob Storage.
- Evite
INSERTunitários — agrupe comCOPY INTO,INSERT…SELECTou CTAS. OPENROWSET(BULK …)consulta arquivos externos inline; obcpestá disponível em Preview para carga pelo lado do cliente.
Superfície T-SQL do Fabric Warehouse
Suportado
Tabelas, views, stored procedures, funções, roles e permissões · colunas IDENTITY · MERGE · TRUNCATE TABLE · tabelas #temp com escopo de sessão · CTEs (CTEs aninhadas em Preview) · um subconjunto de query/join hints · sp_rename para colunas · ALTER TABLE ADD de coluna anulável / DROP COLUMN / adicionar-remover constraints NOT ENFORCED · ALTER COLUMN em Preview · transações explícitas com snapshot isolation.
Não suportado
Triggers · Materialized views · Synonyms · CREATE USER · BULK LOAD · consultas recursivas · estatísticas multi-coluna criadas manualmente · SELECT … FOR XML · SET ROWCOUNT · SET TRANSACTION ISOLATION LEVEL · PREDICT · tipo de dado vector · / ou \ em nomes de schema/tabela.
O SQL analytics endpoint (de um Lakehouse ou mirrored database) é somente leitura: sem DDL, sem INSERT/UPDATE/DELETE. Ele suporta views, funções, stored procedures, RLS, CLS e DDM.
Lakehouses com schema habilitado
- Schemas agrupam tabelas por domínio e vêm ligados por padrão em lakehouses novos. Todo lakehouse com schema tem um schema
dboque não pode ser renomeado nem removido. Nomes de schema aceitam apenas letras, dígitos e underscores. - Grave em um deles com
df.write.mode("overwrite").saveAsTable("marketing.campaigns"). Sem o prefixo de schema, a tabela vai paradbo. - Schema shortcuts mapeiam um schema inteiro para o schema de outro lakehouse ou uma pasta do ADLS Gen2.
- Spark SQL entre workspaces usa o nome em quatro partes
workspace.lakehouse.schema.table(três partes para um lakehouse sem schema). - Limitação: lakehouses com schema habilitado não podem ser compartilhados pelo compartilhamento de workspace — exponha-os por shortcuts em um lakehouse que o usuário já alcança.
Objetivo 2.3Ingerir e transformar dados de streaming
A pilha do Real-Time Intelligence
Escolhendo um engine de streaming
| Eventstream | Spark Structured Streaming | KQL update policy | Dataflow Gen2 | |
|---|---|---|---|---|
| Código | Canvas sem código (SQL operator em Preview) | PySpark / Scala | KQL | Power Query M |
| Latência | Segundos | Segundos a minutos (micro-batch) | No momento da ingestão | Minutos (lote) |
| Riqueza de transformação | Baixa — filter, fields, aggregate, join, union, expand | Ilimitada | Média — qualquer KQL sobre o extent que chega | Alta, mas em lote |
| Persona | Integrador, analista | Data engineer | Desenvolvedor KQL | Analista |
| Escolha quando | Rotear muitas fontes para muitos destinos com transformação leve | Joins complexos, scoring de ML, estado customizado | Remodelar dados enquanto chegam num Eventhouse | O requisito não é realmente streaming |
Eventstream
Fontes
Azure
Event Hubs · IoT Hub · Event Grid · Service Bus · Blob Storage events · Azure Data Explorer Preview · IoT Operations
CDC
Azure SQL DB · Azure SQL MI · SQL Server em VM · PostgreSQL · MySQL · Cosmos DB · Oracle Preview · MongoDB Preview · Mirrored database change feed Preview
Mensageria
Apache Kafka · Confluent Cloud · Amazon MSK · Amazon Kinesis · Google Cloud Pub/Sub · MQTT Preview · Solace PubSub+ Preview
Nativas do Fabric
Workspace item events · OneLake events · Job events · Capacity events · Anomaly detection events Preview
Customizadas
Custom endpoint / custom app (connection string no protocolo Kafka) · HTTP Preview
Dados de exemplo
Bicycles · Yellow Taxi · Stock market · Buses · Clima em tempo real — para demos e laboratórios de estudo
Operadores de transformação
| Operador | O que faz |
|---|---|
| Filter | Mantém eventos que atendem a uma condição (checagens de null, comparações, conforme o tipo do campo) |
| Manage fields | Adiciona, remove e renomeia campos; muda tipos de dados |
| Aggregate | Soma / mínimo / máximo / média numa janela de tempo |
| Group by | Agregações sobre eventos numa janela de tempo, agrupadas por um ou mais campos, com todos os tipos de janela |
| Union | Combina dois ou mais streams com nomes e tipos de campo iguais; campos que não batem são descartados |
| Expand | Uma linha por elemento de um array |
| Join | Combina dois streams por uma condição de correspondência |
| SQL operator Preview | SQL code-first para janelamento, joins e agregações avançadas |
Destinos
- Eventhouse — dois modos: direct ingestion (caminho mais rápido, eventos brutos direto para uma tabela KQL) ou event processing before ingestion (aplica os operadores antes).
- Lakehouse — grava em Delta. Formato de entrada JSON, Avro ou CSV. Ajuste Minimum rows (1 – 2.000.000) e Maximum duration (1 minuto – 2 horas): menos linhas ou duração menor ⇒ mais arquivos pequenos.
- Derived stream — o próprio stream transformado, republicado para que vários destinos (e o Real-Time hub) o consumam. Suporta pause/resume.
- Activator — para regras e alertas.
- Custom endpoint — aplicações externas leem pelo protocolo Kafka.
- Spark notebook Preview — entrega os eventos a um job de Structured Streaming.
- Tamanho máximo de mensagem 1 MB; retenção máxima 90 dias; garantia de entrega at least once; capacity recomendada F4 ou maior.
- O destino Lakehouse aplica schema enforcement com base no primeiro registro. Colunas extras em eventos posteriores são descartadas, colunas ausentes viram
NULLe um registro sem nenhuma interseção falha na conversão de schema. Não aponte uma fonte com schema variável (como CDC de banco) direto para um destino Lakehouse — use um Eventhouse, ou DeltaFlow. - DeltaFlow Preview achata o JSON aninhado do Debezium (CDC) num schema tabular, registra-o no schema registry do Fabric, cria as tabelas de destino automaticamente e trata a evolução de schema.
Eventhouse, KQL databases e OneLake
- Um Eventhouse é um container que abriga uma ou mais KQL databases que compartilham sua capacity e seus recursos. Cada database ganha um KQL queryset embutido.
- Por padrão o serviço é suspenso quando fica ocioso e reativa em poucos segundos. O capacity planner permite definir um cronograma semanal recorrente em blocos de 60 minutos com um mínimo de CU por bloco (mínimo padrão de 2 CU) mais autoscale acima disso — é a resposta quando a questão diz "as consultas nunca podem pagar penalidade de cold start no horário comercial".
- Os dados são indexados e particionados por hora de chegada, e é por isso que KQL filtrado por tempo é tão rápido.
OneLake availability — "uma cópia lógica"
Habilite no nível de database ou de tabela (com backfill opcional das tabelas existentes) e os dados do KQL também são materializados como Delta no OneLake, legíveis por Spark, SQL endpoint, Warehouse, Lakehouse e Direct Lake — sem custo extra de armazenamento. A política de retenção do database também governa a cópia no OneLake.
// Padrão: agrupa até arquivos Parquet de ~200–256 MB ou até 3 horas. Faixa: 5 min – 3 h. .alter-merge table Telemetry policy mirroring dataformat=parquet with (IsEnabled=true, TargetLatencyInMinutes=5) // Latência 00:00:00 significa que tudo já está no OneLake .show table mirroring operations
Enquanto estiver habilitado você não pode renomear tabelas, mudar o tipo de uma coluna, aplicar row-level security, nem excluir / truncar / purgar dados. Desabilite, faça a alteração e reabilite. E reduzir o TargetLatencyInMinutes cria muitos arquivos pequenos e degrada a leitura — a resposta errada clássica para "as consultas ficaram mais lentas depois que reduzimos a latência".
Tabelas nativas vs. OneLake shortcuts vs. query acceleration
| Tabela KQL nativa | OneLake shortcut | Shortcut + query acceleration | |
|---|---|---|---|
| Onde o dado fica | Dentro do Eventhouse | Externamente, referenciado | Externamente, com uma janela quente em cache |
| Performance | Melhor | Menor | Quase nativa para dados recentes |
| Duplicação | Sim | Nenhuma | Apenas o cache |
| Escolha quando | O dado é consultado e atualizado constantemente | Acesso ocasional ou ad hoc a Delta externo | Consultas frequentes sobre dados Delta externos recentes |
O query acceleration mantém em cache os dados do shortcut dentro de uma janela configurável em dias (herdada do database pai por padrão), com base no modificationTime do log Delta. Habilite na criação do shortcut (botão Accelerate) ou depois via Manage → Data policies → Query acceleration. Funciona apenas com tabelas Delta, exige workspace Admin / Member / Contributor e, por conformidade, convém manter o Eventhouse na mesma região dos dados.
Processando dados com KQL
// ---- filtragem e formato ---- | where Level == "Error" and Timestamp between (ago(1d) .. now()) | where Message has "timeout" // 'has' = correspondência de termo indexado, RÁPIDO | where Message contains "time" // varredura de substring, LENTO — saiba a diferença | take 10 / | limit 10 // linhas arbitrárias, sem garantia de ordem | top 10 by Duration desc // ordenado | project Timestamp, DeviceId, Duration | project-away RawPayload | project-rename ts = Timestamp | extend Minutes = Duration / 1m | distinct DeviceId | sort by Timestamp desc // ---- agregação ---- | summarize count(), dcount(DeviceId), sum(Bytes), avg(Latency), min(Timestamp), max(Timestamp), percentile(Latency, 95), percentiles(Latency, 50, 90, 99), make_list(EventId), make_set(Region), arg_max(Timestamp, *), // a linha mais recente inteira por grupo arg_min(Timestamp, Status), take_any(*) by Region, bin(Timestamp, 5m) // ---- séries temporais ---- | make-series Total = sum(Bytes) default=0 on Timestamp from ago(7d) to now() step 1h by DeviceId | extend (anomalies, score, baseline) = series_decompose_anomalies(Total) | render timechart // ---- joins ---- Devices | join kind=leftouter (Telemetry | summarize LastSeen = max(Timestamp) by DeviceId) on DeviceId | join kind=inner hint.strategy=broadcast (SmallLookup) on $left.Id == $right.Key | lookup (DimDevice) on DeviceId // left-outer otimizado contra uma dimensão pequena | union withsource=SourceTable Errors, Warnings // ---- semiestruturado ---- | extend p = parse_json(Payload) | extend City = tostring(p.location.city), Temp = todouble(p.temp) | mv-expand tag = p.tags to typeof(string) | parse Message with "user=" User " action=" Action // ---- utilidades ---- let threshold = 500; let hot = materialize(Telemetry | where Timestamp > ago(1h)); // cacheia uma subconsulta reutilizada let demo = datatable(Id:int, Name:string) [1, "a", 2, "b"]; | extend Ingested = ingestion_time() // quando o Kusto recebeu, vs. hora do evento | serialize | extend Delta = Value - prev(Value, 1)
Tipos de join — a tabela completa
| Tipo | Retorna | Colunas de saída |
|---|---|---|
innerunique (padrão!) | Linhas da esquerda deduplicadas pela chave de join, casadas com a direita | Os dois lados |
inner | Inner join padrão, sem dedup | Os dois lados |
leftouter / rightouter | Todas as linhas daquele lado, com nulls onde não houver correspondência | Os dois lados |
fullouter | Todas as linhas dos dois lados | Os dois lados |
leftsemi / rightsemi | Linhas daquele lado que têm correspondência | Somente aquele lado |
leftanti / rightanti | Linhas daquele lado que não têm correspondência | Somente aquele lado |
1. O tipo de join padrão é innerunique, não inner. Ele deduplica silenciosamente o lado esquerdo, então as contagens saem menores do que o esperado. Sempre declare kind=inner quando quiser um inner join de verdade.
2. Coloque a tabela menor à esquerda do join para melhor desempenho — o oposto do hábito em SQL.
Update policies e materialized views
.create table RawLogs (OriginalRecord:string) .create table ParsedLogs (Timestamp:datetime, ThreadId:int, Message:string) .create function ExtractLogs() { RawLogs | parse OriginalRecord with "[" Timestamp:datetime "] [ThreadId:" ThreadId:int "] " Message:string | project-away OriginalRecord } .alter table ParsedLogs policy update @'[{ "IsEnabled": true, "Source": "RawLogs", "Query": "ExtractLogs()", "IsTransactional": true, "PropagateIngestionProperties": false }]' // Descartar a cópia bruta depois de transformada .alter-merge table RawLogs policy retention softdelete = 0s
| Propriedade | Significado |
|---|---|
IsEnabled | Liga/desliga |
Source | A tabela cuja ingestão dispara a política |
SourceIsWildCard | Trata Source como padrão (SourceTable*); a função então usa $source_table |
Query | A transformação, geralmente uma função armazenada |
IsTransactional | true ⇒ uma falha na política também faz a ingestão de origem falhar. Padrão false, o que significa que dados ruins ficam só na tabela de origem |
PropagateIngestionProperties | Leva tags de extent e hora de criação para a tabela de destino |
ManagedIdentity | Obrigatório se a consulta ler tabelas de outro database |
Update policies disparam em .ingest, .set, .append, .set-or-append, .set-or-replace, .move extents e .replace extents. Não podem fazer consultas cross-cluster, callouts, nem usar nomes qualificados database()/cluster(). Investigue falhas com .show ingestion failures | where OriginatesFromUpdatePolicy == true.
Update policy vs. materialized view: uma update policy transforma no momento da ingestão e grava numa segunda tabela (boa para parsing, divisão, filtragem). Uma materialized view (.create materialized-view) mantém uma agregação atualizada incrementalmente sobre uma tabela de origem (boa para rollups com summarize/arg_max que você consulta o tempo todo).
Spark Structured Streaming
from pyspark.sql import functions as F from pyspark.sql.types import StructType, StructField, StringType, DoubleType, TimestampType schema = StructType([ StructField("deviceId", StringType(), False), StructField("temp", DoubleType(), True), StructField("eventTime",TimestampType(),True)]) raw = (spark.readStream.format("eventhubs").options(**ehConf).load()) parsed = (raw .withColumn("body", F.col("body").cast("string")) .select(F.from_json("body", schema).alias("e")) .select("e.*")) query = (parsed .repartition(48) # alinhar aos cores disponíveis .writeStream .format("delta") .option("checkpointLocation", "Files/checkpoints/telemetry") .outputMode("append") .partitionBy("deviceId") .trigger(processingTime="1 minute") .toTable("silver.telemetry"))
# Watermark = quanto tempo esperar por eventos atrasados antes de descartá-los e fechar o estado windowed = (parsed .withWatermark("eventTime", "10 minutes") .groupBy(F.window("eventTime", "5 minutes"), "deviceId") # TUMBLING .agg(F.avg("temp").alias("AvgTemp"), F.count("*").alias("Readings"))) # HOPPING / deslizante: windowDuration e depois slideDuration F.window("eventTime", "10 minutes", "5 minutes") # SESSION: timeout de intervalo F.session_window("eventTime", "5 minutes") # Upsert numa tabela Delta a partir de um stream def upsert(batch_df, batch_id): batch_df.createOrReplaceTempView("updates") batch_df.sparkSession.sql(""" MERGE INTO silver.telemetry AS t USING updates AS u ON t.deviceId = u.deviceId AND t.eventTime = u.eventTime WHEN MATCHED THEN UPDATE SET * WHEN NOT MATCHED THEN INSERT *""") (parsed.writeStream .foreachBatch(upsert) .option("checkpointLocation", "Files/checkpoints/upsert") .trigger(availableNow=True) # processa tudo o que há disponível e para .start())
| Configuração | Opções | Observações |
|---|---|---|
| Output mode | append · update · complete | append para destinos Delta. complete reescreve todo o resultado a cada lote — só para agregações. |
| Trigger | processingTime="1 minute" · availableNow=True · once=True · contínuo | availableNow é o trigger moderno de "processe o acumulado e pare" — ideal para pipelines micro-batch agendados. |
| Checkpoint | checkpointLocation | Obrigatório. Guarda offsets e estado; apagá-lo reprocessa tudo do zero. Um checkpoint por query. |
| Optimize write | spark.databricks.delta.optimizeWrite.enabled = True | Mescla/divide partições na escrita para você não precisar fazer repartition() na mão. |
Para streaming em produção use um Spark job definition com política de retry, e não um notebook, e monitore na aba Structured Streaming do monitoring hub (Input rate, Process rate, Input rows, Batch duration, Operation duration).
Windowing functions — uma tabela, três engines
| Janela | Comportamento | Sobreposição | Eventstream / SQL | Spark | KQL |
|---|---|---|---|---|---|
| Tumbling | Segmentos fixos, contíguos, sem sobreposição | Não | TumblingWindow(second, 10) | window("ts","10 seconds") | summarize … by bin(ts, 10s) |
| Hopping | Tamanho fixo, avançando por um salto; um evento pode cair em várias janelas | Sim | HoppingWindow(second, 10, 5) | window("ts","10 seconds","5 seconds") | range + mv-expand, ou make-series |
| Sliding | Emite apenas quando o conteúdo da janela muda (um evento entra ou sai) | Sim | SlidingWindow(second, 10) | Aproximada com um salto pequeno | series_fir() sobre uma série |
| Session | Cresce enquanto eventos continuam chegando; fecha após um intervalo de timeout ou uma duração máxima | Não | SessionWindow(second, 5, 10) | session_window("ts","5 minutes") | Operador scan |
| Snapshot | Agrupa eventos com exatamente o mesmo timestamp | Não | GROUP BY System.Timestamp() | groupBy("ts") | summarize … by ts |
- Toda janela emite seu resultado no fim da janela.
- Uma hopping window cujo salto é igual ao tamanho da janela é uma tumbling window.
- "Reportar a média a cada minuto sobre os últimos cinco minutos" = hopping (tamanho 5 min, salto 1 min). "Reportar a média de cada bloco de cinco minutos" = tumbling.
Activator
- Objects são formados agrupando eventos por uma object key (ID do dispositivo, ID da conta). As regras então são avaliadas por instância de objeto.
- Regras stateless julgam cada evento isoladamente e disparam em frações de segundo. Regras stateful mantêm memória por objeto:
BECOMES,INCREASES/DECREASES,EXIT RANGE, heartbeat (ausência de dados) e agregações sobre uma janela de lookback. - As regras disparam na entrada em um novo estado, e é isso que suprime alertas repetidos.
- Fontes: Eventstream, Fabric workspace item events, Azure Blob events, Real-Time dashboards, relatórios do Power BI (observações periódicas atreladas ao agendamento de refresh), regras de consulta SQL sobre um Warehouse Preview.
- Ações: e-mail, mensagem no Teams, fluxo do Power Automate — e itens do Fabric: pipeline, notebook, Spark job definition, Dataflow, Copy job, user data function.
Monitorar e otimizar uma solução de análise
O domínio para o qual os candidatos menos se preparam, e que vale exatamente o mesmo que os outros dois. Três grupos de objetivos: monitorar itens do Fabric, identificar e resolver erros, e otimizar performance em seis engines diferentes.
Objetivo 3.1Monitorar itens do Fabric
As superfícies de monitoramento, e qual usar
| Superfície | Escopo | Use para |
|---|---|---|
| Monitoring hub | Todos os itens a que você tem acesso, no tenant inteiro | "O que rodou, quando, e deu certo?" Um único lugar para pipelines, notebooks, Dataflows, Spark jobs, Copy jobs, modelos semânticos, manutenção de Lakehouse e mais |
| Recent runs do item | Um item | Histórico de execuções só daquele item |
| Capacity Metrics app | Uma capacity | Consumo de CU, bursting, overages, throttling, e qual operação os causou |
| Workspace monitoring | Um workspace | Logs de diagnóstico e métricas detalhadas num Eventhouse consultável (30 dias) |
| Admin monitoring workspace | Tenant | Feature usage and adoption, atividade no nível do tenant |
| Purview / unified audit log | Tenant | Quem fez o quê — auditoria de compliance e segurança |
Detalhes do monitoring hub: mostra as 100 atividades mais recentes por tipo de item nos últimos 30 dias. Filtre por status, tipo de item, hora de início, quem submeteu e localização; pesquise por nome; ordene e reorganize colunas. Em cada linha você pode abrir um painel de detalhes (status, hora de início, duração, detalhe do erro), abrir Historical runs para o histórico completo de 30 dias daquele item, e configurar notificações de falha de agendamento Preview (exige Contributor ou Write no item). Dataflow Gen1 não aparece.
Monitorar a ingestão de dados
- Pipelines — histórico de execuções mais as execuções por atividade. A saída da Copy activity traz
rowsRead,rowsCopied,rowsSkipped,throughput,dataConsistencyVerification, e a duração dividida em tempo de fila e de transferência. - Copy job — tem seu próprio dashboard em tempo real: status e progresso por tabela, histórico de execuções e alertas de falha; também aparece no workspace monitoring.
- Eventstream — status dos nós, métricas de throughput e métricas de erro na live view e no workspace monitoring.
- Ingestão do Eventhouse —
.show ingestion failuresé o comando mais importante; a página System overview do Eventhouse mostra taxa de ingestão, principais databases ingeridos, armazenamento, uso de computação e mudanças de schema. - Mirroring — status de replicação e contagem de linhas por tabela na página de monitoramento do mirrored database; uma capacity pausada interrompe a replicação.
Monitorar a transformação de dados
- Spark — cinco pontos de entrada: o monitoring hub, o Recent runs do item, o monitoramento contextual dentro do notebook (progresso do job por célula, tasks, executores, logs), o monitoramento inline do Spark job definition e os deep links da atividade Spark no pipeline. Por trás deles estão o Spark Advisor (dicas de código e análise de erro em tempo real), o Apache Spark History Server estendido e os snapshots de notebook, que capturam o código e a saída exatos de uma execução.
- Dataflow Gen2 — histórico de refresh com duração e performance por query, integrado ao monitoring hub.
- Warehouse — as views de Query Insights mais as DMVs ao vivo:
-- Retido por 30 dias; até ~15 minutos de latência; somente consultas de usuário SELECT TOP 100 distributed_statement_id, query_hash, allocated_cpu_time_ms, label, command FROM queryinsights.exec_requests_history ORDER BY allocated_cpu_time_ms DESC; -- Detecção de cold start: leitura remota diferente de zero significa que NÃO estava em cache SELECT distributed_statement_id, query_hash, data_scanned_remote_storage_mb, data_scanned_memory_mb, data_scanned_disk_mb, command FROM queryinsights.exec_requests_history ORDER BY data_scanned_remote_storage_mb DESC; SELECT * FROM queryinsights.long_running_queries ORDER BY median_total_elapsed_time_ms DESC; SELECT * FROM queryinsights.frequently_run_queries ORDER BY number_of_successful_runs DESC; SELECT * FROM queryinsights.exec_sessions_history; SELECT * FROM queryinsights.sql_pool_insights; -- alocação de recursos e pressão no pool -- Estado ao vivo (agora, não histórico) SELECT * FROM sys.dm_exec_requests; SELECT * FROM sys.dm_exec_sessions; SELECT * FROM sys.dm_exec_connections;
Adicione OPTION (LABEL = 'carga_noturna_fato') aos comandos do seu ETL. O label chega ao queryinsights, então você consegue filtrar o histórico por uma etapa específica do pipeline. Consultas com o mesmo formato (mesma estrutura, predicados diferentes) são agregadas juntas nas views de insight.
Monitorar o refresh de modelos semânticos
- Modelos Import e DirectQuery: histórico de refresh no modelo, mais uma atividade Semantic model refresh que você pode encadear no fim de um pipeline.
- Modelos Direct Lake não fazem "refresh" de dados — eles fazem framing (uma operação só de metadados, de segundos, que aponta o modelo para os arquivos Delta mais recentes) e carregam segmentos de coluna na memória sob demanda (transcoding). O que você monitora é o sucesso do framing e se as consultas caíram para DirectQuery.
Monitoramento de capacity e alertas
- Capacity Metrics app — a página Compute mostra CU segundos por operação, separados em interactive e background; o detalhe de timepoint entra num único intervalo de 30 segundos para nomear a operação culpada; a aba Overages plota carryforward, uso cumulativo e burndown; a tabela de system events registra episódios de throttling; Minutes to burndown estima a recuperação.
- Alertas — regras do Activator sobre um Eventstream, KQL queryset ou Real-Time dashboard; alertas sobre um visual do Power BI; notificação de falha de pipeline via atividade do Outlook ou Teams, ou as notificações de falha de agendamento nativas; notificações de capacity configuradas pelo capacity admin.
Objetivo 3.2Identificar e resolver erros
Trate esta seção como uma consulta sintoma → causa → correção. O exame formula assim: "um job falha com X — o que você deve fazer primeiro?"
Erros de pipeline
| Sintoma | Causa provável | Correção |
|---|---|---|
| Atividade falha com um código de erro de conector | Credenciais expiradas, firewall, caminho errado | Leia ErrorCode, Message e failureType na saída da atividade; teste a conexão; verifique o status do gateway |
| Atividades seguintes rodam mesmo com uma anterior falhando | Seta de dependência definida como On completion em vez de On success | Corrija a condição de dependência |
| O pipeline "tem sucesso" mas nada foi carregado | Todas as atividades em caminhos On skip/On completion, ou um ForEach sobre um array vazio | Adicione uma checagem de contagem com Lookup mais uma atividade Fail para tornar o vazio um erro explícito |
| Falhas transitórias de rede | Sem retry configurado | Defina Retry e Retry interval na aba General da atividade |
| Atividade longa que trava | Timeout padrão generoso demais | Defina um Timeout explícito |
| Mensagem de erro não capturada | — | No caminho de falha, registre @activity('Copy1').error.message e @pipeline().RunId numa tabela |
Erros do Dataflow Gen2
- Comece pelo Refresh history → o refresh que falhou → o detalhe de erro por query.
- Falhas de staging — os itens internos
DataflowsStagingLakehouse/DataflowsStagingWarehouse. Se o staging está falhando, verifique throttling de capacity antes de qualquer outra coisa. - Erros de data destination — incompatibilidade de schema entre a saída da query e a tabela de destino existente, ou um tipo que o destino não aceita. Verifique a configuração de fixed vs. dynamic schema do destino.
- Erros de gateway — gateway on-premises offline, desatualizado ou sem o driver daquela fonte.
- Erros de avaliação — um passo M falhando com os dados reais (nulls, tipos inesperados). Corrija com
try … otherwiseou um passo explícito de conversão de tipo. - Query folding quebrado — um passo que não faz folding puxa tudo para o mashup engine e o refresh fica lentíssimo. Clique com o botão direito num passo → View native query; mova os passos que não dobram para o final.
Erros de notebook e Spark
| Erro | Significado | Correção |
|---|---|---|
HTTP 430 TooManyRequestsForCapacity | Não há mais Spark vCores disponíveis na capacity (incluindo burst) | Cancele um job ativo no monitoring hub, espere a fila, use um pool menor ou aumente o SKU. Jobs interativos são rejeitados; jobs de background entram na fila |
| Sessão não inicia / erro de Livy | Capacity esgotada, ou um publish de environment que falhou | Verifique a capacity; republique o environment; verifique o provisionamento de VNet do Private Link (10–15 min no primeiro job) |
OOM de executor / Java heap space | Join com skew, collect() gigante, poucas partições | Nó maior, broadcast do lado pequeno, salting da chave com skew, aumentar spark.sql.shuffle.partitions, nunca fazer collect() de um DataFrame grande |
Py4JJavaError | O wrapper Python expondo uma exceção da JVM | Ignore o traceback do Python e vá até a linha Caused by do Java |
ModuleNotFoundError depois do publish | Biblioteca instalada no escopo da sessão, não no Environment | Adicione à lista de bibliotecas do Environment e publique; use Full mode para jobs agendados |
Escrita concorrente / ConcurrentAppendException | Dois jobs gravando na mesma tabela Delta | Particione as escritas com replaceWhere, serialize-as, ou faça retry |
Erros de Eventhouse e Eventstream
.show ingestion failures— o primeiro comando de qualquer investigação em Eventhouse. Motivos comuns: schema incompatível, um ingestion mapping ausente ou errado, JSON/CSV malformado e throttling.- Acrescente
| where OriginatesFromUpdatePolicy == truepara isolar falhas causadas por uma update policy. - Se uma update policy transacional está falhando, a ingestão de origem também falha — defina
IsTransactional = falsese sucesso parcial for aceitável. - Eventstream: conectividade da fonte (credenciais, firewall, consumer group já em uso), falhas de escrita no destino e schema drift contra o schema do primeiro registro do destino Lakehouse. Verifique status dos nós e métricas de erro na live view.
Erros de T-SQL e do SQL analytics endpoint
- T-SQL não suportado — triggers, materialized views, synonyms, CTEs recursivas,
SET TRANSACTION ISOLATION LEVEL. É aqui que código migrado quebra primeiro. - Uma tabela nova do Lakehouse não aparece no SQL endpoint — a sincronização de metadados do endpoint é assíncrona. Atualize os metadados do endpoint (ou use a atividade de pipeline Refresh SQL endpoint depois da etapa de carga). Este é um cenário de prova bastante comum.
- Aviso de non-scalable operation — um
TOP/ORDER BYglobal forçou execução em nó único. AdicioneOPTION (FORCE DISTRIBUTED PLAN)ou reestruture. - Erros de lock / conflito — transações explícitas abertas por muito tempo. Mantenha as transações curtas e orientadas a lote; faça retry com backoff exponencial.
- Violações de constraint que nunca acontecem — lembre que as constraints são
NOT ENFORCED; duplicatas são culpa do seu ETL, não do engine.
Erros de OneLake shortcut
- Credenciais expiradas ou revogadas na cloud connection — a causa mais frequente de um shortcut que "funcionava ontem". Recrie ou atualize a conexão.
- Erros de permissão em shortcuts internos — a autorização usa a identidade de quem chama; a pessoa precisa de permissão de leitura no item de destino, não apenas no shortcut.
- Direct Lake sobre SQL, ou T-SQL em modo delegated identity, passa a identidade do dono do item chamador em vez da do usuário. Mude para Direct Lake sobre OneLake, ou T-SQL em modo user identity.
- Tabela não reconhecida — um shortcut em
Tables/que não é uma tabela Delta válida, ou tem espaço no nome, ou está num subdiretório. - Limite de encadeamento — mais de 5 níveis de shortcut apontando para shortcut.
- Latência entre regiões — reduza com o cache de shortcuts (retenção de 1 a 28 dias; arquivos acima de 1 GB não são cacheados).
- ADLS Gen2 atrás de firewall — precisa de workspace identity mais trusted workspace access, ou um managed private endpoint.
Objetivo 3.3Otimizar performance
Otimizar uma tabela de Lakehouse
Quase todo problema de performance em Lakehouse é o problema dos arquivos pequenos: escritas de streaming ou micro-batch frequentes produzem milhares de arquivos Parquet minúsculos, e o overhead de metadados domina a leitura.
| Operação | O que faz | Observações |
|---|---|---|
OPTIMIZE | Bin-compaction: mescla arquivos Parquet pequenos em arquivos maiores | Rode depois de ingestão pesada ou de muitos updates |
| V-Order | Ordenação, encoding e compressão do layout Parquet no momento da escrita | Escritas ~15% mais lentas, até 50% mais compressão e leituras muito mais rápidas. Continua 100% compatível com o Parquet open source |
VACUUM | Exclui arquivos não referenciados mais antigos que o limite de retenção | Retenção padrão de 7 dias. Intervalos menores são recusados a menos que spark.databricks.delta.retentionDurationCheck.enabled = false; encurtar destrói o histórico de time travel e pode quebrar leitores concorrentes |
ZORDER BY | Coloca valores relacionados juntos para que o file skipping funcione em colunas de filtro de alta cardinalidade | Combine com particionamento numa coluna de baixa cardinalidade |
| Merge transactions / limpeza de deletion vectors | Reincorpora os arquivos de deletion vector aos dados Parquet | Disponível no diálogo de manutenção |
-- Manutenção de tabela via Spark SQL OPTIMIZE silver.orders ZORDER BY (CustomerId, OrderDate); VACUUM silver.orders RETAIN 168 HOURS; -- 168 h = o padrão de 7 dias DESCRIBE HISTORY silver.orders; -- V-Order, três níveis de controle SET spark.sql.parquet.vorder.default; -- inspecionar (padrão da sessão: false) SET spark.sql.parquet.vorder.default = TRUE; -- sessão ALTER TABLE person SET TBLPROPERTIES("delta.parquet.vorder.enabled" = "true"); -- tabela
(df.write.format("delta").mode("overwrite") .option("replaceWhere", "start_date >= '2026-01-01' AND end_date <= '2026-01-31'") .option("parquet.vorder.enabled", "true") .saveAsTable("myschema.mytable")) spark.conf.set("spark.databricks.delta.optimizeWrite.enabled", True) # dimensiona arquivos na escrita spark.conf.set("spark.databricks.delta.stats.collect", True) # estatísticas para file skipping
Warehouse: o V-Order é aplicado automaticamente ao Parquet que ele produz, qualquer que seja o método de ingestão. Desabilite apenas num warehouse puramente de escrita intensiva — e note que ele não pode ser reabilitado depois de desligado no nível do warehouse.
Spark / Lakehouse: o V-Order vem desligado por padrão em workspaces novos, para manter as escritas rápidas. Ligue-o para tabelas gold de leitura intensiva, ou use um resource profile de leitura. O OPTIMIZE o aplica como parte da manutenção.
Orientação de particionamento: particione apenas tabelas grandes o suficiente para justificar, numa coluna de baixa cardinalidade (ano, mês, região), mirando partições na faixa de centenas de MB a alguns GB. Particionar demais recria o problema dos arquivos pequenos. Use ZORDER, não particionamento, para colunas de alta seletividade. Rode a manutenção ad hoc pelo Lakehouse explorer (clique com o botão direito na tabela → Maintenance), ou agende-a com a atividade de pipeline Lakehouse maintenance Preview. Acompanhe no monitoring hub pelos nomes de atividade contendo TableMaintenance. OPTIMIZE e VACUUM valem apenas para tabelas Delta — não para Hive Parquet, ORC, AVRO ou CSV.
Otimizar um pipeline
- Aumente o degree of copy parallelism da Copy activity; habilite staging quando o caminho direto for lento.
- Num ForEach, desligue Sequential e defina o Batch count (máx. 50) para controlar a concorrência.
- Empurre a filtragem para a origem (uma query em vez de ler a tabela inteira) para trafegar menos dados.
- Prefira o Copy job a lógica incremental artesanal quando o padrão for convencional — ele particiona e paraleliza automaticamente.
- Nunca itere linha a linha. Substitua um ForEach interno que insere uma linha por vez por uma cópia em lote ou uma stored procedure.
- Adeque a computação ao trabalho — não suba uma sessão Spark para mover um arquivo.
Otimizar um data warehouse
| Alavanca | Orientação |
|---|---|
| Estatísticas | O Fabric mantém automaticamente estatísticas de histograma, comprimento médio de coluna e cardinalidade. Você ainda pode fazer CREATE STATISTICS / UPDATE STATISTICS manualmente numa janela de manutenção. Estatísticas multi-coluna não podem ser criadas manualmente. |
| Tipos de dados | Prefira smallint/int/bigint a decimal para números inteiros. Nunca escreva decimal puro (vira decimal(18,0), 9 bytes por linha). Dimensione varchar(n) pelo dado — evite varchar(8000) e varchar(max). Use date/time/datetime2, nunca strings para datas. Declare NOT NULL onde puder. |
| Paridade de tipos | Mantenha tipos idênticos nos dois lados de comparações em JOIN e WHERE, para evitar conversões implícitas. |
| Cold start | A primeira execução paga por carregar dados do OneLake para a memória mais as estatísticas automáticas. data_scanned_remote_storage_mb = 0 significa totalmente em cache — o estado ideal. |
| Ingestão | COPY INTO em paralelo; arquivos ≥ 100 MB (nunca abaixo de 4 MB); transações em lote; evite inserts unitários em gotejamento. |
| Formato da consulta | Projete apenas as colunas necessárias; filtre cedo; evite SELECT *; prefira TRUNCATE+CTAS a UPDATE/DELETE grandes. |
| Transações | Snapshot isolation, ACID. Mantenha-as curtas — o rollback é barato (reversão de versão Parquet), mas transações longas seguram locks. Monitore sys.dm_tran_locks. |
| Controle de plano | OPTION (FORCE DISTRIBUTED PLAN) quando aparecer o aviso de non-scalable operation. |
| Modelo | Um star schema tem desempenho melhor que uma tabela larga desnormalizada para cargas de BI. |
Otimizar Eventstreams e Eventhouses
- Batching vs. streaming ingestion policy — o batching (padrão) troca um pouco de latência por arquivos bem maiores e desempenho de consulta muito melhor; a streaming ingestion dá visibilidade em menos de um segundo, com custo maior. Escolha por tabela.
- Caching (hot) policy — a quantidade de dados recentes mantida no SSD do cluster. Alargar a janela quente acelera as consultas e custa mais; estreitar faz o inverso. Ajuste para cobrir o período que as pessoas realmente consultam.
- Retention policy — por quanto tempo o dado sobrevive. A retenção precisa ser ≥ a janela quente para fazer sentido.
- Update policies para remodelar na ingestão; materialized views para agregações mantidas incrementalmente que as consultas acessam o tempo todo.
- Partitioning policy — só para padrões específicos de alta cardinalidade ou hora de ingestão embaralhada; não é o padrão.
- Eventstream — dimensione a capacity (F4+), mantenha Minimum rows e Maximum duration do destino Lakehouse altos o bastante para evitar arquivos pequenos, e rode Optimize table in notebook nos destinos Delta de streaming.
- Não baixe o
TargetLatencyInMinutesda mirroring policy abaixo do necessário — arquivos pequenos prejudicam todos os leitores downstream.
Otimizar performance do Spark
Aceleradores específicos do Fabric
- Native Execution Engine — um engine vetorizado em C++ que executa operações Spark nativamente; ganhos grandes sem mudar código.
- Intelligent Cache — cache automático, local ao nó, de arquivos Delta/Parquet/CSV lidos com frequência.
- Autotune — ajuste por consulta, guiado por ML, de shuffle partitions, limiares de broadcast e preferências de join.
- Adaptive Query Execution — replaneja em tempo de execução usando estatísticas reais.
Sessão e concorrência
- Starter pools para início em 5–10 s; custom live pools quando você precisa de bibliotecas pré-instaladas e ainda quer ~5 s.
- High concurrency mode para compartilhar uma sessão entre notebooks (e entre atividades de notebook num pipeline).
- Dynamic executor allocation + autoscale em vez de um pool fixo superdimensionado.
- Bursting (3×) vem ligado; um capacity admin pode desabilitar o bursting em nível de job para que um único job não monopolize a capacity.
Ajuste no nível da consulta
- Faça broadcast do lado pequeno de um join (
F.broadcast(df)). - Trate skew com salting da chave quente ou deixe o AQE dividi-la.
- Ajuste
spark.sql.shuffle.partitionsao volume de dados, não ao padrão. cache()/persist()num DataFrame reutilizado várias vezes — e façaunpersist()depois.- Evite UDFs em Python; prefira funções nativas ou
pandas_udf. - Nunca faça
collect()de um DataFrame grande no driver.
Limites de concorrência (por cores)
1 CU = 2 Spark vCores; burst padrão 3×. Numa F64: 128 base → 384 com burst, limite de fila 64. Jobs de background (disparados por pipeline, pelo scheduler, Spark job definitions) entram numa fila FIFO e expiram em 24 horas; jobs interativos de notebook são rejeitados com HTTP 430, nunca enfileirados.
Otimizar performance de consulta (camada semântica)
| Direct Lake | Import | DirectQuery | |
|---|---|---|---|
| Engine | VertiPaq, lendo Delta diretamente | VertiPaq, sobre uma cópia | Delegado à fonte |
| Refresh | Framing — só metadados, segundos | Refresh completo dos dados, minutos a horas | Nenhum |
| Latência dos dados | Baixa | Tão desatualizada quanto o último refresh | Ao vivo |
| Licenciamento | Exige capacity do Fabric | Qualquer licença | Qualquer licença |
- Direct Lake sobre OneLake lê quaisquer tabelas Delta do Fabric, suporta composite models e colunas calculadas, aplica segurança na camada semântica e não tem fallback para DirectQuery.
- Direct Lake sobre SQL lê tabelas e views de Lakehouse/Warehouse, respeita RLS de SQL — e cai para DirectQuery quando encontra uma view não materializada ou controle de acesso granular baseado em SQL. O fallback é controlado pela propriedade Direct Lake behavior. Fallback costuma ser o motivo de um relatório Direct Lake "ficar lento de repente".
- Os guardrails escalam com o SKU — contagem de arquivos Parquet, de row groups, de linhas e memória. Ultrapassar a memória não é um bloqueio rígido; causa paging e degradação. F2–F8: 300 M linhas, 10 GB, 3 GB de memória. F64/P1: 1,5 B linhas, tamanho ilimitado, 25 GB de memória. F512/P4: 12 B linhas, 200 GB de memória.
- A melhor otimização isolada para um modelo Direct Lake é ter tabelas Delta bem mantidas: V-Order aplicado, arquivos compactados, contagem de row groups abaixo do guardrail.
- Não suportado em Direct Lake: tipos de coluna complexos (Binary, GUID), floats não numéricos, strings acima de 32.764 caracteres, hierarquias definidas pelo usuário em tabelas Direct Lake, gateways, workspaces pessoais e workspaces de origem em outra região.
Folhas de consulta
Números que vale decorar
| Valor | A que se aplica |
|---|---|
| 1 CU = 2 Spark vCores; burst 3× | Dimensionamento de Spark. F64 → 384 vCores |
| 10 min / 60 min / 24 h | Estágios de throttling: overage protection → interactive delay (20 s) → interactive rejection → background rejection |
| 5–64 min · 24 h | Janelas de smoothing: interativo · background |
| 30 segundos | Um timepoint de capacity (2.880 por dia) |
| 7 dias | Retenção padrão do VACUUM |
| 30 dias | Retenção do Query Insights · histórico do monitoring hub · retenção do workspace monitoring |
| 1–28 dias | Retenção do cache de OneLake shortcut (arquivos > 1 GB não são cacheados) |
| 100.000 / 10 / 5 | Shortcuts por item / por caminho do OneLake / profundidade máxima de encadeamento |
| 1 MB · 90 dias · at least once | Eventstream: tamanho máximo da mensagem · retenção máxima · garantia de entrega |
| 5 min – 3 h | Faixa do TargetLatencyInMinutes do mirroring de Eventhouse para OneLake (mira arquivos de 200–256 MB) |
| 1 – 2.000.000 linhas · 1 min – 2 h | Destino Lakehouse do Eventstream: minimum rows · maximum duration |
| 2–10 estágios (padrão 3) | Deployment pipelines |
| 20 agendamentos · batch count 50 no ForEach | Por pipeline · limite de paralelismo do ForEach |
| 1.000 / 1.000 / 10.000 / 1 MB | Variable library: variáveis · value sets · células totais · tamanho do item |
| 1 TB por CU | Armazenamento gratuito de mirroring (F64 → 64 TB) |
| 20 minutos | Expiração padrão da sessão Spark (o pool é desalocado 2 min depois) |
| 24 horas | Expiração da fila de jobs Spark de background |
| 4 MB / 100 MB – 1 GB | Ingestão no Warehouse: tamanho mínimo absoluto / tamanho recomendado de arquivo |
| 700 / 1000 | Nota de aprovação |
Fluxogramas de decisão em palavras
"Onde estes dados devem ficar?"
Streaming/telemetria/logs, pessoal de KQL → Eventhouse. DML completo em T-SQL e transações multi-tabela → Warehouse. Spark, não estruturado, ML → Lakehouse. Aplicação OLTP → SQL database no Fabric. Já existe em outro lake → shortcut. É um banco operacional que você quer continuamente → mirror.
"Como trago estes dados?"
Contínuo de um banco operacional suportado → Mirroring. Já está num lake → Shortcut. Bulk/incremental/CDC agendado, sem orquestração → Copy job. Precisa de orquestração ou muitas atividades → Pipeline + Copy activity. Analista com Power Query → Dataflow Gen2. Complexo/customizado → Notebook. Orientado a eventos → Eventstream.
"Por que está lento?"
Lakehouse → arquivos pequenos; rode OPTIMIZE, verifique V-Order e particionamento. Warehouse → cache frio, tipos de dados ruins, estatísticas desatualizadas, plano em nó único. Spark → skew, shuffle partitions, falta de broadcast, inicialização de sessão. Eventhouse → cache quente pequeno demais, sem materialized view, filtro por substring não indexada. Power BI → fallback do Direct Lake ou guardrail estourado.
"Quem pode ver o quê?"
Workspace inteiro → workspace role. Um item → item permission. Tabelas/pastas específicas para um Viewer → OneLake security role. Linhas específicas → RLS. Colunas específicas → CLS. Ocultar um valor da maioria dos usuários → dynamic data masking. Classificar e proteger na exportação → sensitivity label.
KQL vs. T-SQL vs. PySpark — a mesma operação, três dialetos
| Operação | KQL | T-SQL | PySpark |
|---|---|---|---|
| Filtrar | | where x > 5 | WHERE x > 5 | .filter(F.col("x") > 5) |
| Selecionar colunas | | project a, b | SELECT a, b | .select("a","b") |
| Nova coluna | | extend c = a + b | SELECT a + b AS c | .withColumn("c", F.col("a")+F.col("b")) |
| Agregar | | summarize sum(x) by g | GROUP BY g | .groupBy("g").agg(F.sum("x")) |
| Top N | | top 10 by x desc | SELECT TOP 10 … ORDER BY x DESC | .orderBy(F.desc("x")).limit(10) |
| Contagem distinta | dcount(x) | COUNT(DISTINCT x) | F.countDistinct("x") |
| Linha mais recente por chave | summarize arg_max(ts, *) by k | ROW_NUMBER() … WHERE rn = 1 | row_number().over(w) |
| Bucket de tempo | bin(ts, 1h) | DATETRUNC(hour, ts) | F.window("ts","1 hour") |
| Expandir array | | mv-expand tags | — | F.explode("tags") |
| Parsear JSON | parse_json(col) | JSON_VALUE() | F.from_json(col, schema) |
| Upsert | .set-or-append | MERGE | DeltaTable.merge() |
Um plano de estudos de quatro semanas
A lista de prontidão
Marque cada item somente quando conseguir explicá-lo para outra pessoa sem consultar nada.
- Domínio 1 · Implementar e gerenciar
- Configurar Spark workspace settings — pools, tamanhos de nó, autoscale, dynamic allocation, high concurrency, environments
- Configurar workspace settings de domain, OneLake e Apache Airflow
- Configurar controle de versão (Git integration) e implementar database projects
- Criar e configurar deployment pipelines, deployment rules e variable libraries
- Implementar controles de acesso no nível de workspace e de item
- Implementar controles de acesso de linha, coluna, objeto e pasta/arquivo
- Implementar dynamic data masking
- Aplicar sensitivity labels e endossar itens
- Implementar e usar Fabric audit logs e workspace monitoring
- Configurar e implementar OneLake security roles
- Escolher entre Dataflow Gen2, pipeline e notebook
- Projetar e implementar agendamentos e event-based triggers
- Implementar padrões de orquestração com notebooks e pipelines, incluindo parâmetros e expressões dinâmicas
- Domínio 2 · Ingerir e transformar
- Projetar e implementar cargas full e incremental
- Preparar dados para um modelo dimensional (SCD 1/2/3, surrogate keys, membros inferidos)
- Projetar e implementar um padrão de carga para dados de streaming
- Escolher um data store apropriado
- Escolher entre Dataflows Gen2, notebooks, KQL e T-SQL para transformação
- Criar e gerenciar OneLake shortcuts
- Implementar mirroring
- Ingerir dados usando pipelines e Copy job
- Transformar dados usando PySpark, SQL e KQL
- Desnormalizar, agrupar e agregar dados
- Tratar dados duplicados, ausentes e atrasados
- Escolher um engine de streaming apropriado
- Escolher entre tabelas nativas e OneLake shortcuts no Real-Time Intelligence
- Escolher entre query acceleration e OneLake shortcuts padrão
- Processar dados usando Eventstreams, Spark Structured Streaming e KQL
- Criar windowing functions
- Domínio 3 · Monitorar e otimizar
- Monitorar ingestão, transformação e refresh de modelo semântico
- Configurar alertas
- Identificar e resolver erros de pipeline
- Identificar e resolver erros de Dataflow Gen2
- Identificar e resolver erros de notebook
- Identificar e resolver erros de Eventhouse
- Identificar e resolver erros de Eventstream
- Identificar e resolver erros de T-SQL
- Identificar e resolver erros de OneLake shortcut
- Otimizar uma tabela de Lakehouse
- Otimizar um pipeline
- Otimizar um data warehouse
- Otimizar Eventstreams e Eventhouses
- Otimizar performance do Spark
- Otimizar performance de consulta
Pare de ler e comece a fazer. Construa uma coisa de ponta a ponta numa trial capacity: coloque um CSV num Lakehouse, transforme com um notebook, carregue um star schema pequeno num Warehouse, faça dados de exemplo passarem por um Eventstream até um Eventhouse, escreva três consultas KQL contra ele, conecte o workspace ao Git e promova tudo por um deployment pipeline de dois estágios. Tudo em que você tropeçar nessa hora é o que precisa revisar.