SaveMyCert
Log in
5 of 5 free questions left today·for unlimited practice
Ingest and transform data

Batch Ingestion in Fabric: Data Stores, Shortcuts, Mirroring, and Pipelines

14 min readDP-700 · Ingest and transform dataUpdated

Batch ingestion in Microsoft Fabric starts with two decisions — which store the data lands in (Lakehouse, Warehouse, Eventhouse, or a semantic model on top) and whether the data needs to move at all, because OneLake shortcuts and mirroring can make external data queryable without copying it. Only then do you pick the machinery: pipelines to copy and orchestrate, and Dataflows Gen2, Spark notebooks, T-SQL, or KQL to transform. DP-700 weights this topic heavily and probes it as a chain of choices: store, access pattern, transform tool, then the data-quality work — deduplicating, filling or filtering missing values, and handling late-arriving rows. This lesson walks the whole chain with the two decision tables the exam leans on most: Lakehouse vs Warehouse vs Eventhouse, and shortcut vs mirror vs copy.

What you’ll learn
  • Choose between a Lakehouse, Warehouse, Eventhouse, and semantic model for a given workload and skill set
  • Select the right transformation tool among Dataflows Gen2, notebooks, T-SQL, and KQL
  • Create internal and external OneLake shortcuts and explain what they do and don't move
  • Decide when mirroring beats shortcuts or pipeline copies for operational sources
  • Ingest batch data with pipeline Copy activities and orchestrate downstream transforms
  • Handle duplicate, missing, and late-arriving data in PySpark, T-SQL, and KQL

Choosing the right Fabric data store

Choose the store by workload and by the language your team will query it with: a Lakehouse for file-based and Spark-centric engineering over Delta tables, a Warehouse for full T-SQL analytics with multi-table transactions, an Eventhouse (housing KQL databases) for high-volume telemetry, logs, and time-series queried in near real time, and a semantic model as the BI consumption layer over any of them — not a landing zone for raw data.

StoreBest forPrimary languageWrite accessFormat
LakehouseFiles plus tables, Spark transformations, medallion layers, semi-structured dataPySpark / Spark SQLSpark; SQL analytics endpoint is read-only T-SQLDelta/Parquet in OneLake
WarehouseSQL-first dimensional serving, multi-table transactions, T-SQL DMLT-SQLFull T-SQL read/writeDelta in OneLake
Eventhouse (KQL database)Streaming telemetry, logs, IoT time-series, free-text and trace explorationKQLStreaming and batch ingestionColumnar store, exposable as Delta in OneLake
Semantic modelBI serving to Power BI, measures and relationships (Direct Lake over OneLake)DAXNot a data store for ingestionModel over Delta tables

Two distinctions decide most exam questions. First, the Lakehouse's SQL analytics endpoint is read-only — if the scenario requires T-SQL INSERT/UPDATE/MERGE or stored procedures writing data, the answer is a Warehouse. Second, everything above stores or exposes data as Delta in OneLake, so choosing one store does not wall data off from the other engines — shortcuts and the shared format keep a single copy queryable everywhere.

Choosing a transformation tool: Dataflows Gen2, notebooks, T-SQL, or KQL

Match the tool to the transformation's complexity, the data's scale and shape, and the team's skills. Dataflows Gen2 is Power Query in Fabric: a low-code, visual tool with hundreds of connectors, right for business-analyst-friendly cleansing and mapping of light-to-moderate volumes, with output written to a Lakehouse, Warehouse, or other destinations. Notebooks (PySpark/Spark SQL) are the code-first choice for large-scale, complex transformations — custom logic, reusable functions, unit-testable code, machine-friendly formats like JSON and Parquet — and generally the most capacity-efficient option at scale. T-SQL (stored procedures and views in a Warehouse, orchestrated by pipelines) fits SQL-skilled teams doing set-based dimensional transforms on structured, already-tabular data. KQL transforms live where telemetry lives: shaping, parsing, and aggregating event data inside an Eventhouse, including materializing transformations with update policies as data streams in.

The exam phrases this as persona-plus-requirement scenarios:

  • "Citizen developers", "least code", "analysts who know Power Query" → Dataflow Gen2.
  • "Hundreds of gigabytes", "complex business logic", "data scientists", "reusable library" → notebook.
  • "Team knows T-SQL", "stored procedures", "transform inside the Warehouse" → T-SQL.
  • "Transform events as they're ingested into the Eventhouse", "parse log text" → KQL.

Remember the neighbouring skill from Domain 1: a pipeline is not a transformation engine — it copies and orchestrates. A pipeline calling a notebook or stored procedure is the standard pairing: Copy activity for movement, code for logic.

OneLake shortcuts: one copy of data, many engines

A shortcut is a pointer in OneLake that makes data stored elsewhere appear as if it lived in your Lakehouse, Warehouse, or KQL database — no data is moved or duplicated, and reads always see the current state of the source. Shortcuts are OneLake's answer to data sprawl: instead of every team copying the same dataset into its own workspace, one physical copy is referenced from wherever it's needed.

Shortcuts come in two families:

  • Internal (OneLake) shortcuts point at data in other Fabric items — another Lakehouse's tables or files, a Warehouse, a mirrored database, or a KQL database — across workspaces. A gold Lakehouse can shortcut to a silver Lakehouse in another workspace and query its Delta tables in place.
  • External shortcuts point at storage outside Fabric, such as Azure Data Lake Storage Gen2, other cloud object stores, or Dataverse. The data stays where it is (and where its lifecycle is managed); Fabric engines read it through the shortcut, with caching available to reduce repeated cross-cloud reads and egress.

Placement matters: a shortcut created under a Lakehouse's Tables section must reference Delta-formatted data to surface as a queryable table, while shortcuts under Files can point at any files and formats. Security follows the shortcut model too — access is evaluated against the target's permissions via the calling user or a delegated connection, so a shortcut is not a way around source authorization.

Choose a shortcut when the source is already analytics-ready (Delta/Parquet files, another team's gold tables) and freshness should be "whatever the source has right now." It is instant to create, costs no storage, and removes an entire copy pipeline from your estate.

Mirroring: near-real-time replicas of operational databases

Mirroring continuously replicates an operational database into OneLake as Delta tables, giving you a near-real-time, analytics-ready copy with no pipelines to build or schedule. You configure it once against a supported source — Azure SQL Database, Azure Cosmos DB, or Snowflake, among a growing set — and Fabric performs an initial snapshot, then applies the source's ongoing changes (inserts, updates, deletes) to the replica automatically, using the source's change feed.

What you get is a mirrored database item whose tables are ordinary Delta tables in OneLake: query them through the SQL analytics endpoint with T-SQL, shortcut them into a Lakehouse for Spark transformation, and build Direct Lake semantic models on them. The replica is read-only — it is a landing zone for analytics, not a writable store — and because replication is change-based, it offloads analytical queries from the operational system far better than repeated pipeline extracts that re-scan source tables.

Mirroring solves a specific problem: operational databases are not query-friendly analytical sources. Before mirroring, the standard answer was an incremental pipeline with watermarks and merges; mirroring replaces that whole apparatus for supported sources. Exam scenarios signal it with phrases like "replicate an Azure SQL Database into Fabric with minimal effort," "near real time without building pipelines," or "analysts need current Cosmos DB data without impacting the app." If the source is a file store rather than a database, mirroring is the wrong tool — that's shortcut territory; if the data needs heavy reshaping on the way in, mirroring alone isn't enough — you still transform downstream, typically with Spark over shortcuts to the mirrored tables.

Shortcut, mirror, or copy? Picking an access pattern

The three access patterns answer one question differently: where does the physical data live, and who keeps it current? A shortcut leaves data at the source and reads it live; mirroring maintains a continuously updated replica in OneLake; a pipeline copy takes a point-in-time snapshot you own and schedule.

AspectOneLake shortcutMirroringPipeline copy
Data movementNone — virtual referenceContinuous replication into OneLakePhysical copy on each run
FreshnessAlways current (reads the source)Near real timeAs of last run
Source typesOneLake items, ADLS Gen2, other cloud stores, DataverseSupported operational databases (Azure SQL Database, Cosmos DB, Snowflake, ...)Broadest — hundreds of connectors
Transformation on the way inNoneNone (replica matches source)Yes — copy plus downstream transforms
Ongoing effortNoneNone after setupYou own schedules, watermarks, failures
Best whenData already analytics-ready in an accessible storeOperational DB needed fresh in OneLake without pipelinesSource unsupported by the other two, or you need shaping, isolation, or history at ingestion

Scenario. A retailer's sales run in Azure SQL Database, clickstream files land in ADLS Gen2 as Parquet, and a legacy on-premises system exports CSVs nightly. The DP-700 answer: mirror the Azure SQL Database (fresh operational data, zero pipelines), shortcut the ADLS Gen2 clickstream (already analytics-ready files, no copy needed), and run a pipeline copy for the legacy CSVs (no mirroring support, needs shaping into Delta on the way in). One solution, three patterns, each earning its place.

Ingesting data with pipelines

Pipelines are Fabric's batch ingestion and orchestration workhorse: the Copy activity moves data from hundreds of sources into a Lakehouse, Warehouse, or Eventhouse at scale, and control-flow activities (ForEach, Lookup, If, Notebook, Stored procedure, Dataflow) sequence the work around it. A typical ingestion pipeline looks up configuration, iterates a list of source tables with ForEach, runs a parameterized Copy per table into bronze, then invokes a notebook or stored procedure to transform onward — with schedules or event triggers starting the run.

Copy activity choices the exam cares about:

  • Destination and format. Landing in Lakehouse Files keeps raw fidelity (any format); landing in Tables writes Delta and is immediately queryable. Bronze-layer designs usually land files or append-only Delta and defer conforming to Spark.
  • Full vs incremental copies. A source query filtered on a watermark column (driven by Lookup activities against a control table) turns Copy into an incremental extractor; the simpler Copy job item packages common full and incremental copy patterns without building the pipeline scaffolding yourself.
  • Parameterization. One pipeline with parameters for source, schema, and table beats dozens of cloned pipelines — pass values from ForEach over a metadata list.

Keep the division of labor straight: pipelines move and orchestrate but do not transform row internals — that's the job of the notebook, stored procedure, or Dataflow they call. When a scenario says "copy 200 tables nightly and then run transformations," the shape of the answer is a metadata-driven pipeline with ForEach plus Copy, followed by orchestrated transform activities.

Transforming with PySpark, T-SQL, and KQL: denormalize, group, aggregate

The same core transformations — joining, reshaping, aggregating — express naturally in all three languages, and DP-700 expects you to read each. Denormalization means joining normalized tables into wider ones so analytical queries stop paying repeated join costs; it's the standard silver-to-gold step that also feeds dimensional models.

Joining orders to customers, then aggregating revenue by segment:

PySpark:
  wide = orders.join(customers, "customer_id", "left")
  result = (wide.groupBy("segment")
    .agg(sum("amount").alias("revenue"),
         countDistinct("order_id").alias("orders")))

T-SQL:
  SELECT c.segment, SUM(o.amount) AS revenue,
         COUNT(DISTINCT o.order_id) AS orders
  FROM dbo.orders AS o
  LEFT JOIN dbo.customers AS c
    ON o.customer_id = c.customer_id
  GROUP BY c.segment;

KQL:
  orders
  | lookup kind=leftouter customers on customer_id
  | summarize revenue = sum(amount),
              orders = dcount(order_id) by segment

Language-mapping cues worth memorizing: PySpark's groupBy().agg(), T-SQL's GROUP BY, and KQL's summarize ... by are the same operation; KQL's lookup/join replaces SQL joins; KQL pipes read top-to-bottom as a data flow. Choose the language by where the data lives and who maintains the code (the tool-choice rules earlier), not by capability — all three group, join, window, and aggregate. One practical Fabric note: if the transform must write to a Lakehouse table, it runs in Spark, because the Lakehouse's T-SQL surface is read-only; T-SQL DML transforms belong in a Warehouse.

Handling duplicate, missing, and late-arriving data

Data-quality handling is a silver-layer responsibility: bronze keeps what arrived, silver makes it trustworthy. The exam tests the idiom in each language plus the design pattern behind each problem.

Duplicates. Exact duplicates fall to PySpark's dropDuplicates(["order_id"]) or KQL's distinct. "Keep the latest version per key" needs ranking: in T-SQL, ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY modified_at DESC) and keep rn = 1; in KQL, summarize arg_max(modified_at, *) by order_id; in PySpark, a window with row_number(). The durable fix is an idempotent load — MERGE on the business key — so reruns and overlapping extracts can't create duplicates in the first place.

Missing values. First decide the semantics — is null "unknown," "not applicable," or "bad record"? Then: fill defaults (fillna(), COALESCE, KQL coalesce()), impute from related data, drop rows that fail hard requirements (dropna() on key columns), or quarantine failures to an errors table for review rather than silently discarding them. Missing dimension attributes surface as explicit "Unknown" members so reports don't quietly lose rows on inner joins.

Late-arriving data. Rows can arrive after their period was already processed — a sale dated yesterday landing after last night's run. Batch designs handle this with a lookback window (each run re-extracts the last N days and MERGEs, so stragglers reconcile), event-dated reprocessing of affected partitions, and — when the late arrival is a fact referencing an unseen dimension member — the inferred-member pattern from the loading-patterns lesson. The common thread: because reconciliation means applying the same rows again, every one of these designs only works if the load is idempotent.

Tip. This is DP-700's largest single topic and it's tested as chained decisions: expect 'choose the store' questions hinging on the read-only Lakehouse SQL endpoint vs Warehouse T-SQL DML, 'choose the tool' questions keyed to personas (Power Query analysts → Dataflow Gen2; large-scale complex logic → notebook; event parsing in an Eventhouse → KQL), and 'shortcut vs mirror vs copy' questions keyed to the source type — analytics-ready files point to shortcuts, supported operational databases with 'minimal effort / near real time' point to mirroring, everything else to pipeline copies. Also expect code-reading items that map GROUP BY, groupBy().agg(), and summarize across languages, and data-quality items where arg_max, ROW_NUMBER ... PARTITION BY, and lookback-window MERGE patterns are the correct dedupe and late-arrival answers.

Key takeaways
  • Store choice is workload plus language: Lakehouse for Spark and files, Warehouse for full T-SQL DML and multi-table transactions, Eventhouse for telemetry queried with KQL, semantic model as the BI layer — and the Lakehouse SQL analytics endpoint is read-only.
  • Tool choice follows persona and scale: Dataflows Gen2 for low-code Power Query users, notebooks for large or complex code-first transforms, T-SQL for Warehouse-centric SQL teams, KQL for shaping event data in an Eventhouse.
  • Shortcuts are zero-copy pointers — internal to other OneLake items, external to ADLS Gen2 or Dataverse; table shortcuts need Delta format, and access still honors the target's permissions.
  • Mirroring keeps a near-real-time, read-only Delta replica of Azure SQL Database, Cosmos DB, or Snowflake in OneLake with no pipelines to build; it replaces watermark-and-merge extracts for supported sources.
  • Pick the access pattern by ownership of freshness: shortcut = read the source live, mirror = managed replica, pipeline copy = scheduled snapshot you control and can transform on the way in.
  • Pipelines copy and orchestrate but don't transform row internals — a metadata-driven ForEach + parameterized Copy activity feeding notebooks or stored procedures is the canonical batch design.
  • GROUP BY, groupBy().agg(), and summarize ... by are the same operation in T-SQL, PySpark, and KQL; denormalizing with joins is the standard silver-to-gold step.
  • Dedupe with row_number/arg_max keeping the latest row per key, quarantine bad records instead of silently dropping them, and absorb late-arriving data with lookback windows over an idempotent MERGE load.

Frequently asked questions

When should I choose a Lakehouse over a Warehouse in Fabric?

Choose a Lakehouse when you need Spark-based transformation, storage of raw files alongside tables, or semi-structured data — it's the natural home of the medallion architecture. Choose a Warehouse when the team works in T-SQL and needs to write with it: INSERT, UPDATE, MERGE, stored procedures, and multi-table transactions. The deciding detail in many exam questions is that a Lakehouse's SQL analytics endpoint is read-only — T-SQL writes require a Warehouse.

What is the difference between a OneLake shortcut and mirroring?

A shortcut is a virtual pointer: the data stays in its source (another OneLake item, ADLS Gen2, Dataverse), nothing is copied, and reads see the source's current state. Mirroring physically replicates a supported operational database (Azure SQL Database, Cosmos DB, Snowflake) into OneLake as Delta tables and keeps the replica current automatically. Shortcut when the data is already analytics-ready files or tables; mirror when the source is an operational database you want fresh in OneLake without building pipelines.

Do OneLake shortcuts copy data or affect its security?

Shortcuts never copy data — they reference it in place, so there is one physical copy no matter how many workspaces shortcut to it. Security is evaluated against the shortcut's target: for internal shortcuts the caller needs access to the target item, and for external shortcuts access flows through the connection's credentials. A shortcut therefore can't be used to bypass source permissions, and deleting a shortcut deletes only the pointer, not the underlying data.

Which transformation tool should a team with only Power Query skills use?

Dataflows Gen2 — it is Power Query running in Fabric, with a visual, low-code editor, a large connector library, and output destinations including Lakehouses and Warehouses. It suits business analysts doing cleansing, mapping, and light reshaping at light-to-moderate volume. When transformations become very large-scale or logic-heavy, the exam's expected pivot is to Spark notebooks, which handle scale and complex custom code more efficiently.

How do you keep only the latest version of each record when a batch contains duplicates?

Rank rows per business key by a recency column and keep the top one: T-SQL uses ROW_NUMBER() OVER (PARTITION BY key ORDER BY modified_at DESC) filtered to rn = 1, PySpark uses the same row_number over a window (or dropDuplicates for exact duplicates), and KQL uses summarize arg_max(modified_at, *) by key. Then make the load idempotent by MERGEing on the business key, so re-running a batch can never introduce duplicates into the target.

What does it mean to handle late-arriving data in a batch design?

Rows sometimes arrive after the load that should have included them — a transaction dated yesterday landing today. Batch designs absorb this with a lookback window: each run re-extracts the last several days and MERGEs, so stragglers reconcile automatically. When a late arrival is a fact referencing a dimension member you haven't loaded yet, insert an inferred placeholder member and complete it later. All of these depend on the load being idempotent, since the same rows will be applied more than once.

Test yourself on this topic
Practice questions with full explanations.
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.