SaveMyCert
Log in
5 of 5 free questions left today·for 30 a day
Databricks DEA practice

Databricks DEA sample questions — 25 answered and explained

25 Databricks DEA sample questions written to the official Databricks Certified Data Engineer Associate exam guide, grouped by exam domain and weighted like the real exam. Each shows the correct answer, why every other option is wrong, and the lesson that teaches it. None of them repeat the examples on the other Databricks DEA practice pages.

On this page
25
answers included
Full bank
535
on the practice page
Domains
7
weighted like the exam
Free, no account
5/day
a free account allows 30 a day

Domain 1: Databricks Intelligence Platform

6% of the Databricks DEA exam, so 2 of the 25 questions on this page.

Question 1Databricks Intelligence Platform

An analyst ran an UPDATE an hour ago that set every row's status to 'shipped' in the Delta table sales.orders. DESCRIBE HISTORY shows that version 41 is the last version before that update. The data engineer must return the table to its state at version 41. Which command does that?

Choose one.

  • a
    RESTORE TABLE sales.orders TO VERSION AS OF 41 Correct

    Correct. RESTORE writes a new commit that makes the table's state match version 41, keeping the history.

  • b
    SELECT * FROM sales.orders VERSION AS OF 41

    This time-travel query reads version 41 but leaves the current table unchanged.

  • c
    CREATE TABLE sales.orders_v41 SHALLOW CLONE sales.orders VERSION AS OF 41

    This creates a new table, sales.orders_v41, that references version 41's files; sales.orders itself keeps the bad update.

  • d
    VACUUM sales.orders RETAIN 1 HOURS

    VACUUM deletes unreferenced data files. It never restores data, and a short retention can destroy the files needed to go back.

The concept

RESTORE returns a Delta table to an earlier version.

Why that’s the answer

Delta keeps prior versions in the transaction log. DESCRIBE HISTORY lists them, VERSION AS OF and TIMESTAMP AS OF read them, and RESTORE TABLE ... TO VERSION AS OF (or TO TIMESTAMP AS OF) makes the current table match one of them by adding a new commit. Reading an old version or cloning it into a new table leaves sales.orders unchanged, and VACUUM only removes files.

How to reason it out
  1. Note the goal: change the current table, not just read history or copy it.
  2. Recall the commands that read history (SELECT ... VERSION AS OF) or copy it (CLONE ... VERSION AS OF) vs change it (RESTORE).
  3. Reject VACUUM, which only removes files.
  4. Choose RESTORE TABLE ... TO VERSION AS OF 41.

Exam tip: Read the past with VERSION AS OF; go back to it with RESTORE.

Databricks Platform Architecture, Delta Lake, Unity Catalog and Compute (Data Engineer Associate) — the lesson that teaches this.

Question 2Databricks Intelligence Platform

Auditors ask a data engineer to query a Delta table as it was 20 days ago. The table uses default retention settings, and a maintenance job runs VACUUM on it every week with no RETAIN clause. The TIMESTAMP AS OF query for 20 days ago fails. What is the cause?

Choose one.

  • a
    The transaction log's default retention is 7 days, so the commit for that older version was removed

    Log entries are kept for 30 days by default (delta.logRetentionDuration), so the commit is still described; it is the data files that are missing.

  • b
    Unity Catalog blocks time-travel queries against a managed table once a scheduled VACUUM job has run on that table

    Unity Catalog places no such restriction; time travel fails here because the files are gone.

  • c
    Time travel reaches back no further than the data versions recorded in the most recent transaction log checkpoint

    Checkpoints summarise the log for faster reads; they do not limit how far back time travel can go.

  • d
    VACUUM deleted the data files that the 20-day-old version needed, which were past the 7-day default Correct

    Correct. VACUUM removes files no longer referenced by the current version once they are older than the retention threshold (7 days by default), so older versions can no longer be read.

The concept

VACUUM limits how far back time travel can reach.

Why that’s the answer

Time travel needs both the commit in the transaction log and the data files that version referenced. VACUUM deletes data files that are no longer referenced by the current table and are older than the retention threshold, 7 days by default (delta.deletedFileRetentionDuration). A weekly VACUUM therefore removes the files for versions older than about a week, even though their log entries (kept 30 days by default) remain.

How to reason it out
  1. Note the maintenance job: weekly VACUUM at default retention.
  2. Recall the default VACUUM retention threshold: 7 days.
  3. Recall that time travel needs the old data files, not only the log entry.
  4. Conclude that VACUUM removed the files for the 20-day-old version.

Exam tip: Time travel reaches only as far back as VACUUM has left the data files.

Databricks Platform Architecture, Delta Lake, Unity Catalog and Compute (Data Engineer Associate) — the lesson that teaches this.

Domain 2: Data Ingestion and Loading

21% of the Databricks DEA exam, so 5 of the 25 questions on this page.

Question 3Data Ingestion and Loading

A SQL-only analytics team loads daily JSON order files from the Unity Catalog volume path /Volumes/sales/raw/orders/ into a table with a scheduled query. They need each file loaded exactly once, without rereading files from previous days. Which statement should the data engineer schedule?

Choose one.

  • a
    CREATE OR REFRESH STREAMING TABLE orders AS SELECT * FROM STREAM read_files('/Volumes/sales/raw/orders/') Correct

    Correct. A streaming table reading STREAM read_files keeps a checkpoint of processed files, so each refresh loads only new files exactly once.

  • b
    CREATE OR REPLACE TABLE orders AS SELECT * FROM read_files('/Volumes/sales/raw/orders/', format => 'json')

    CREATE OR REPLACE TABLE rebuilds the table from every file on each run; it is a full batch reload.

  • c
    INSERT INTO orders SELECT * FROM read_files('/Volumes/sales/raw/orders/')

    INSERT INTO appends every file again on each run, so yesterday's orders are duplicated today.

  • d
    CREATE OR REFRESH MATERIALIZED VIEW orders AS SELECT * FROM read_files('/Volumes/sales/raw/orders/', format => 'json')

    A materialized view stores the result of a query and is refreshed against its sources; it is not designed to track and append newly arrived files.

The concept

Streaming tables give SQL users incremental, exactly-once file ingestion.

Why that’s the answer

read_files is a table-valued function. Used in a batch statement, it reads every file in the path each time, so CREATE OR REPLACE TABLE reloads everything and INSERT INTO duplicates. Wrapped in STREAM inside CREATE OR REFRESH STREAMING TABLE, it becomes an incremental source with its own checkpoint, so each refresh processes only files it has not seen. Databricks positions streaming tables as the scalable SQL replacement for COPY INTO.

How to reason it out
  1. Note the requirements: SQL only, each file exactly once, no rereads.
  2. Recognize that batch reads of read_files reprocess every file.
  3. Choose a streaming table with STREAM read_files, which tracks processed files.

Exam tip: SQL incremental file loads: CREATE OR REFRESH STREAMING TABLE ... FROM STREAM read_files().

Databricks Data Ingestion Patterns and Lakeflow Connect: Choosing an Ingestion Method (Data Engineer Associate) — the lesson that teaches this.

Question 4Data Ingestion and Loading

An analyst has a small CSV of regional sales targets on a laptop and wants it queryable in Unity Catalog this afternoon so it can be joined with existing sales data. The file will not be updated again. Which ingestion method is the most appropriate?

Choose one.

  • a
    Use the workspace's create-or-modify-table file upload page to create a managed table Correct

    Correct. The file upload page turns small local CSV, JSON, Parquet and similar files into a managed Unity Catalog table in a few clicks, which fits a one-off load.

  • b
    Copy the file to a Unity Catalog volume with the Databricks CLI and load it with COPY INTO

    This works, but the CLI setup, the volume and a load statement are extra steps for one small file that the upload page turns into a table directly.

  • c
    Build an Auto Loader pipeline in file notification mode over a folder synced from the laptop

    Auto Loader reads cloud object storage and suits continuous file arrival; for one small, never-updated local file it is setup with no benefit.

  • d
    Set up a partner ingestion tool through Partner Connect and run a one-time sync to a table

    A partner tool brings a new account and configuration for something the built-in upload page does directly.

The concept

Small, one-off local files are loaded with the file upload UI, which creates a managed Unity Catalog table.

Why that’s the answer

The create-or-modify-table page in the workspace accepts small local files (CSV, TSV, JSON, Avro, Parquet, text), previews the schema and writes a managed Delta table into a chosen catalog and schema. It needs CREATE TABLE on the schema and a compute resource. Copying to a volume with the CLI and running COPY INTO also works, but it is the route for files too large for the upload page; Auto Loader and partner tools are designed for recurring or large-scale ingestion, not a one-off small file on a laptop.

How to reason it out
  1. Note the source: a small file on a local machine.
  2. Note the frequency: once.
  3. Choose the built-in file upload page that creates a managed table.

Exam tip: One small local file, loaded once: the file upload page.

Databricks Data Ingestion Patterns and Lakeflow Connect: Choosing an Ingestion Method (Data Engineer Associate) — the lesson that teaches this.

Question 5Data Ingestion and Loading

A vendor sends a single Parquet extract that a data engineer has downloaded to a workstation. The file is far larger than any browser upload in the workspace allows. The data must end up in a Unity Catalog table, and the raw file must be kept for audit under Unity Catalog access control. What should the data engineer do?

Choose one.

  • a
    Split the file into parts small enough for the upload page and upload each part

    Splitting a Parquet file by hand is error-prone, the parts would still go through a browser upload, and the upload page writes a table without keeping the raw file for audit.

  • b
    Upload the file with the volume's UI upload button in Catalog Explorer, then load it from the volume

    Loading from a volume is right, but the volume's UI upload button has a per-file size limit that this file exceeds; for larger files Databricks points to the CLI or SDK.

  • c
    Copy the file to a Unity Catalog volume with the Databricks CLI, then load it from there Correct

    Correct. Volumes store files of any size the cloud storage supports; the CLI or SDK avoids the UI upload limit, the raw file stays in the governed volume, and a load from the volume path creates the table.

  • d
    Copy the file into the DBFS FileStore folder, then create a Unity Catalog table from it

    The DBFS root is a legacy location that Unity Catalog does not govern, so the raw audit copy would sit outside Unity Catalog access control.

The concept

Large local files go into a Unity Catalog volume (via CLI or SDK) and are loaded from there.

Why that’s the answer

The file upload page is meant for small files, and browser uploads into a volume also have a size limit. Volumes themselves hold files up to the cloud storage maximum, and the Databricks CLI (databricks fs cp to a /Volumes path) or SDK can upload large files. The raw file then remains in a governed volume for audit, and read_files or COPY INTO loads it into a table. The DBFS root is not governed by Unity Catalog.

How to reason it out
  1. Recognize that every browser upload path is ruled out by the file's size.
  2. Choose a governed landing place for raw files: a Unity Catalog volume.
  3. Use the CLI or SDK, which are not bound by the browser upload limit.
  4. Load the table from the volume path.

Exam tip: Too big for the upload page: copy to a Unity Catalog volume with the CLI/SDK, then load.

Databricks Data Ingestion Patterns and Lakeflow Connect: Choosing an Ingestion Method (Data Engineer Associate) — the lesson that teaches this.

Question 6Data Ingestion and Loading

A data engineer is planning ingestion for three sources: Workday HR records, partner files landing in an ADLS container, and order events on an Azure Event Hubs stream. The team wants to use the connector that Lakeflow Connect provides for each source, standard or managed. Which plan is correct?

Choose one.

  • a
    A managed connector for Workday, a managed connector for the files, and Auto Loader for Event Hubs

    Auto Loader reads files in cloud object storage, not an event stream, and files in ADLS are read with Auto Loader, a standard connector, rather than a managed connector.

  • b
    A managed connector for Workday, Auto Loader for the files, and Structured Streaming for Event Hubs Correct

    Correct. Workday is a SaaS source with a managed connector; cloud object storage files are a standard-connector source read with Auto Loader; Event Hubs is a message bus read with Structured Streaming or a declarative pipeline.

  • c
    Auto Loader for Workday exports, Auto Loader for the files, and a nightly JDBC read for Event Hubs

    Exporting Workday to files adds a custom export job when a managed Workday connector exists, and Event Hubs is a streaming source read with Structured Streaming, not JDBC.

  • d
    Auto Loader for Workday exports, a managed connector for the files, and Structured Streaming for Event Hubs

    Structured Streaming suits Event Hubs, but Workday has a managed connector so an export job is unnecessary, and ADLS files are read with Auto Loader rather than a managed connector.

The concept

Standard connectors cover cloud storage and message buses; managed connectors cover SaaS applications, databases and file services.

Why that’s the answer

Lakeflow Connect splits sources into two families. Managed connectors cover popular SaaS applications such as Workday and Salesforce, databases through CDC, and file services such as SharePoint, with Databricks handling authentication, incremental logic and retries. Standard connectors are used through Auto Loader for files in cloud object storage and through Structured Streaming or Lakeflow Spark Declarative Pipelines for message buses such as Kafka, Kinesis and Event Hubs.

How to reason it out
  1. Classify each source: SaaS app, cloud storage files, message bus.
  2. Map SaaS to a managed connector.
  3. Map cloud storage files to Auto Loader.
  4. Map the message bus to a streaming read.

Exam tip: SaaS/database = managed connector; cloud files = Auto Loader; message bus = streaming read.

Databricks Data Ingestion Patterns and Lakeflow Connect: Choosing an Ingestion Method (Data Engineer Associate) — the lesson that teaches this.

Question 7Data Ingestion and Loading

A ServiceNow managed connector already lands incident tables in Unity Catalog. The service desk team now needs a cleaned table that standardizes priority codes and drops test records. A developer proposes replacing the connector with a custom notebook that calls the ServiceNow API and applies the rules while fetching. What should the data engineer recommend?

Choose one.

  • a
    Keep the connector and add a pipeline that builds a cleaned silver table from its output Correct

    Correct. The managed connector keeps handling ingestion, and the cleansing rules run downstream as a transformation from the bronze tables into a silver table.

  • b
    Replace the connector with the API notebook so it cleans each record while fetching

    This moves to a less managed layer for something the managed layer does not need to do; the team would take on API paging, incremental logic and retries.

  • c
    Replace the connector with a community connector that allows transformation code in-flight

    A community connector is open source and carries no Databricks SLA; it is meant for sources without managed support, which ServiceNow has.

  • d
    Keep the connector and edit its destination streaming table to apply the cleansing rules

    The connector's destination tables are owned by its ingestion pipeline; editing them by hand would be overwritten or conflict with the pipeline's updates.

The concept

Start with the most managed ingestion layer and put business rules in downstream transformations, not in ingestion.

Why that’s the answer

Databricks recommends starting with the most managed layer and moving down only when that layer cannot meet a requirement, for example when the source is unsupported. Cleansing rules are not an ingestion requirement: the connector lands raw data, and a downstream pipeline turns those bronze tables into a cleaned silver table. Replacing the connector with custom or community code gives up managed authentication, incremental reads and retries for no benefit.

How to reason it out
  1. Check whether the managed connector still meets the ingestion need: it does.
  2. Classify the new requirement: a transformation, not ingestion.
  3. Apply transformations downstream of the raw landed tables.
  4. Move down a layer only when the managed layer cannot ingest the source.

Exam tip: Keep the most managed ingestion layer; do cleansing downstream in bronze-to-silver transformations.

Databricks Data Ingestion Patterns and Lakeflow Connect: Choosing an Ingestion Method (Data Engineer Associate) — the lesson that teaches this.

Domain 3: Data Transformation and Modeling

22% of the Databricks DEA exam, so 6 of the 25 questions on this page.

Question 8Data Transformation and Modeling

A data engineer joins a silver orders DataFrame to a customers DataFrame on customer_id. Some orders arrive before their customer record, and the finance report must still include those orders, with the customer columns empty. Which join should the data engineer use?

Choose one.

  • a
    orders.join(customers, "customer_id", "inner")

    An inner join keeps only orders with a matching customer, so the early orders disappear from the report.

  • b
    orders.join(customers, "customer_id", "left_semi")

    A left semi join keeps only matching orders and returns no customer columns at all.

  • c
    orders.join(customers, "customer_id", "right")

    A right join keeps every customer and drops orders whose customer has not arrived yet.

  • d
    orders.join(customers, "customer_id", "left") Correct

    Correct. A left join keeps every order and fills the customer columns with nulls when no match exists.

The concept

Inner joins keep only matches; left joins keep every row of the left side and add nulls when the right side has no match.

Why that’s the answer

Every order must appear, so orders must be the preserved side: orders.join(customers, ..., "left"). Inner and left semi joins drop unmatched orders (and semi returns no customer columns), and a right join preserves customers instead of orders.

How to reason it out
  1. Decide which table must keep all its rows: orders.
  2. Put that table on the left and use a left join.
  3. Expect nulls in the customer columns for unmatched orders.

Exam tip: Keep every row of one side: put it on the left and use a left join.

Cleaning, Joining and Reshaping Data with PySpark and SQL (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 9Data Transformation and Modeling

A silver orders table has 2 million rows, one per order_id. After an inner join to a customer_addresses table on customer_id, the result has 2.6 million rows, although every order should appear once. What explains the extra rows?

Choose one.

  • a
    The inner join adds rows with nulls for orders that have no address

    An inner join drops unmatched rows; adding null-filled rows is what outer joins do.

  • b
    customer_addresses holds several rows for some customer_id values Correct

    Correct. A join returns one output row for every matching pair, so a customer with three addresses turns each of their orders into three rows.

  • c
    Null customer_id values in both tables are matched to each other

    Nulls never compare equal in a standard equi-join, so null keys produce no matches.

  • d
    Spark ran the join as a cross join because of the key column name

    A join with an equality condition on customer_id is not a cartesian product; a cross join would create far more rows.

The concept

Joins multiply rows when the join key is not unique on one side.

Why that’s the answer

Each output row is a matching pair. If customer_addresses has more than one row per customer_id (billing and shipping, or history), every order for that customer is repeated once per address. Inner joins never add unmatched rows, null keys do not match, and nothing turns an equality join into a cross join.

How to reason it out
  1. Compare the row count before and after the join.
  2. Check whether the join key is unique on the other table.
  3. Fix it by filtering or deduplicating that table to one row per key before joining.

Exam tip: More rows after a join = a non-unique key on the other side.

Cleaning, Joining and Reshaping Data with PySpark and SQL (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 10Data Transformation and Modeling

A data engineer runs this query to attach EU promotions to orders, but orders without a promotion are missing from the result:SELECT o.order_id, o.amount, p.promo_code FROM silver.orders o LEFT JOIN silver.promotions p ON o.promo_id = p.promo_id WHERE p.region = 'EU'Every order must appear, with promo_code filled only for EU promotions. Which change meets this requirement?

Choose one.

  • a
    Move p.region = 'EU' from the WHERE clause into the ON clause of the left join Correct

    Correct. In the ON clause the region test only decides which promotions match; orders with no match still appear with a null promo_code.

  • b
    Change the WHERE clause to p.region = 'EU' OR p.region IS NULL and keep the left join

    This keeps orders with no promotion, but orders linked to a non-EU promotion have a region value, fail both tests and still disappear.

  • c
    Replace the LEFT JOIN with an INNER JOIN and keep the WHERE clause as it is

    An inner join drops orders without a matching promotion, which is the problem the query already has.

  • d
    Replace the LEFT JOIN with a RIGHT JOIN and keep the WHERE clause as it is

    A right join preserves promotions rather than orders, and the WHERE filter still removes rows with a null region.

The concept

A WHERE filter on the right table's columns runs after a left join and removes the null-filled rows, turning it into an inner join.

Why that’s the answer

The left join first keeps every order, then WHERE p.region = 'EU' evaluates to NULL for unmatched orders and to false for non-EU promotions, so both are filtered out. Putting the condition in ON restricts which promotions can match while the left join still preserves every order. Adding OR p.region IS NULL rescues orders with no promotion but still drops orders tied to a US or APAC promotion; inner and right joins preserve the wrong side.

How to reason it out
  1. Note when each clause runs: ON during the join, WHERE after it.
  2. Unmatched rows have null right-side columns, which fail a WHERE equality test.
  3. Check orders with a non-EU promotion too, not only orders with none.
  4. Move right-side filters into ON to keep the left join's guarantee.

Exam tip: Filter the right table of a left join in ON, not in WHERE.

Cleaning, Joining and Reshaping Data with PySpark and SQL (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 11Data Transformation and Modeling

A data engineer joins a 2 TB sales DataFrame to a 30 MB country reference DataFrame on country_code. The Spark UI shows a sort-merge join that shuffles the whole sales DataFrame across the cluster. The engineer must avoid that shuffle without changing any session or cluster configuration. Which code change should the engineer make?

Choose one.

  • a
    broadcast(sales).join(countries, "country_code")

    This asks Spark to copy the 2 TB table to every executor, which is the wrong side and would exhaust memory.

  • b
    sales.repartition("country_code").join(countries, "country_code")

    Repartitioning by the key is itself a full shuffle of the large table, so it adds the cost it was meant to remove.

  • c
    sales.join(broadcast(countries), "country_code") Correct

    Correct. The broadcast hint ships the small table to every executor, so the large table is joined where it sits without a shuffle.

  • d
    sales.crossJoin(countries).filter(sales.country_code == countries.country_code)

    The optimizer turns a cross join followed by an equality filter back into an ordinary equi-join on country_code, so the same sort-merge shuffle remains.

The concept

A broadcast join copies a small table to every executor so the large table does not need to be shuffled.

Why that’s the answer

Wrapping the small side in broadcast() (imported from pyspark.sql.functions) is a join hint that works without touching configuration such as spark.sql.autoBroadcastJoinThreshold. Each executor joins its sales partitions against a local copy of the 30 MB table. Broadcasting the large side is backwards, repartitioning shuffles anyway, and a cross join followed by an equality filter is planned as the same sort-merge equi-join.

How to reason it out
  1. Identify the small side of the join.
  2. Avoid configuration changes, so use a hint in code.
  3. Wrap only the small DataFrame in broadcast().

Exam tip: Large-to-small join: broadcast the small side to skip the shuffle.

Cleaning, Joining and Reshaping Data with PySpark and SQL (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 12Data Transformation and Modeling

A data engineer joins sales to stores on both store_id and region, then selects store_id, region and store_name. The select fails because store_id and region are ambiguous:joined = sales.join( stores, (sales.store_id == stores.store_id) & (sales.region == stores.region), "inner")Which join keeps both keys and returns one copy of each key column?

Choose one.

  • a
    sales.join(stores, "store_id" and "region", "inner")

    Python evaluates "store_id" and "region" to just "region", so this joins on region alone and matches the wrong stores.

  • b
    sales.join(stores, "store_id", "inner").join(stores, "region")

    The second join brings in the stores table again on region only, multiplying rows instead of matching on both keys together.

  • c
    sales.join(stores, (sales.store_id == stores.store_id) | (sales.region == stores.region))

    The OR condition matches rows that agree on either key, and an expression join still keeps both copies of each key column.

  • d
    sales.join(stores, ["store_id", "region"], "inner") Correct

    Correct. Joining on a list of column names matches on both columns and keeps a single copy of each key in the output.

The concept

A join on a list of column names is an equi-join on every listed column that returns one copy of each key.

Why that’s the answer

When keys share names on both sides, passing them as a list, ["store_id", "region"], combines them with AND and removes the duplicate key columns, so selecting store_id is no longer ambiguous. The Python and operator returns one string, chaining two joins re-adds the stores table, and OR matches on either key.

How to reason it out
  1. Both keys must match together, which is an AND of equalities.
  2. Key columns have the same names on both sides.
  3. Use the list-of-names form to get one copy of each key.

Exam tip: Same-named multi-column keys: join on a list of names for one copy of each key.

Cleaning, Joining and Reshaping Data with PySpark and SQL (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 13Data Transformation and Modeling

A billing table and an accounts table share a composite key of account_id and sub_account_id. Top-level accounts have a null sub_account_id in both tables. An inner join on both keys drops every top-level account row. Which join condition matches top-level accounts to themselves without matching them to other sub-accounts?

Choose one.

  • a
    (b.account_id == a.account_id) & ((b.sub_account_id == a.sub_account_id) | b.sub_account_id.isNull())

    A null sub_account_id on the billing side now matches every sub-account row of that account, multiplying the top-level rows.

  • b
    (b.account_id.eqNullSafe(a.account_id)) & (b.sub_account_id == a.sub_account_id)

    Null-safe equality is applied to the wrong key; sub_account_id still uses ==, where null never equals null, so top-level rows are still dropped.

  • c
    (b.account_id == a.account_id) & b.sub_account_id.eqNullSafe(a.sub_account_id) Correct

    Correct. eqNullSafe treats two nulls as equal and a null and a value as unequal, so top-level rows match only each other.

  • d
    (b.account_id == a.account_id) & (b.sub_account_id == a.sub_account_id) with a left join

    The left join keeps the billing rows, but their account attributes come back null because null keys still do not match.

The concept

Standard equality never matches null keys; null-safe equality (eqNullSafe in PySpark, <=> in SQL) does.

Why that’s the answer

In an equi-join, null == null evaluates to null, not true, so rows with a null part of the key never match. eqNullSafe returns true for two nulls and false for null versus a value, which is exactly the required behaviour, but only on the column that can be null. The OR isNull() version fans each top-level row out across all sub-accounts, null-safe equality on account_id leaves the null sub_account_id compared with ==, and a left join only keeps the unmatched rows with empty attributes.

How to reason it out
  1. Spot that part of the composite key can be null on both sides.
  2. Recall that standard equality never matches nulls.
  3. Rule out conditions that match a null to non-null keys.
  4. Use null-safe equality for that key column.

Exam tip: Null keys never match with ==; use eqNullSafe (SQL <=>) when null is a real key value.

Cleaning, Joining and Reshaping Data with PySpark and SQL (Databricks Data Engineer Associate) — the lesson that teaches this.

Domain 4: Working with Lakeflow Jobs

16% of the Databricks DEA exam, so 4 of the 25 questions on this page.

Question 14Working with Lakeflow Jobs

A job has a job parameter named mode. When a run is triggered with mode set to backfill, it should run a full reprocessing notebook; for any other value it should run the incremental notebook instead. The choice must be made inside the job's task graph. Which task type should the data engineer add?

Choose one.

  • a
    For each task iterating over the mode parameter values

    For each runs a nested task once per input value; it loops rather than choosing between two paths.

  • b
    If/else condition task comparing the mode parameter Correct

    Correct. It evaluates a comparison such as the mode parameter equalling backfill and runs the true or false branch.

  • c
    Run Job task that passes the mode parameter to a child job

    A Run Job task triggers another job; it has no comparison to decide which notebook runs.

  • d
    SQL alert task that evaluates the mode parameter value

    A SQL alert evaluates a query condition and notifies subscribers; it does not branch the task graph.

The concept

The If/else condition task adds boolean branching to a job: a single comparison decides whether the true or the false branch runs.

Why that’s the answer

Choosing one of two paths from a parameter value is branching, and the If/else condition task provides it. Its operand can be a job parameter such as {{job.parameters.mode}}, and downstream tasks attach to its true or false outcome. For each loops over inputs, Run Job calls another job, and a SQL alert sends notifications.

How to reason it out
  1. Recognise the need: pick one of two paths from a value.
  2. Recall that branching is done with an If/else condition task.
  3. Attach the backfill notebook to the true outcome and the incremental one to the false outcome.
  4. Reject loop, child-job and alert task types.

Exam tip: Branching in Lakeflow Jobs = If/else condition task; looping = For each.

Lakeflow Jobs Tasks, Dependencies and Control Flow: Retries, Run If, If/Else and For Each (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 15Working with Lakeflow Jobs

A validate notebook counts malformed rows in each batch. If the count is above zero, a quarantine notebook must run; otherwise a publish notebook must run. The job must not report a failure just because bad rows were found. How should the data engineer wire these tasks?

Choose one.

  • a
    Raise an exception in the validate task when the count is positive, and give the quarantine task Run if At least one failed

    This routes correctly but marks validate as Failed on every bad batch, which the requirement rules out.

  • b
    Set the count as a task value, compare it in an If/else condition task, and attach quarantine to true and publish to false Correct

    Correct. A task value carries the count to the condition task, and the true and false outcomes route to the right notebook with no task failing.

  • c
    Return the count with dbutils.notebook.exit and give the quarantine and publish tasks Run if conditions on the validate task

    Run if conditions look only at success or failure of upstream tasks; they cannot read a returned value.

  • d
    Pass the count as a job parameter from the validate task and read it with widgets in the quarantine and publish notebooks

    Job parameters are set when the run is triggered; a task cannot change them during the run.

The concept

Data-driven branching combines a task value (set upstream) with an If/else condition task that compares it.

Why that’s the answer

The decision depends on a value computed during the run, so the validate notebook sets it with dbutils.jobs.taskValues.set, and an If/else condition task evaluates {{tasks.validate.values.bad_rows}} > 0. Quarantine depends on the true outcome and publish on the false outcome. Raising an exception would work only by failing the task, Run if cannot inspect values, and job parameters are fixed at trigger time.

How to reason it out
  1. Note the decision uses a value computed during the run.
  2. Carry it downstream as a task value.
  3. Compare it in an If/else condition task and attach each notebook to an outcome.
  4. Reject designs that fail a task or rely on values fixed at trigger time.

Exam tip: Branch on a computed value: task value + If/else condition task, not exceptions plus Run if.

Lakeflow Jobs Tasks, Dependencies and Control Flow: Retries, Run If, If/Else and For Each (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 16Working with Lakeflow Jobs

An upstream notebook runs dbutils.jobs.taskValues.set("schema_version", 2.0). The next task is an If/else condition with the expression {{tasks.detect.values.schema_version}} == 2, but every run takes the false branch even though the version is 2. What explains this behaviour?

Choose one.

  • a
    Task values are resolved after the job run ends, so the condition sees an empty value

    Task values are available to downstream tasks during the same run; that is their purpose.

  • b
    Float task values are truncated when they are set, so the stored value becomes zero

    Task values are stored as their JSON representation; 2.0 is kept as 2.0.

  • c
    If/else conditions read job parameters rather than task values, so the reference evaluates as false

    Conditions accept task value references such as {{tasks.<task>.values.<key>}} as operands.

  • d
    The == operator compares its operands as strings, so 2.0 and 2 are not equal Correct

    Correct. Equality operators compare as strings; the numeric operators such as >= compare as numbers.

The concept

In an If/else condition task, == and != compare operands as strings, while >, >=, < and <= compare them numerically.

Why that’s the answer

The value 2.0 is serialised as the string 2.0, and == compares it with the string 2, which differs, so the condition is false every time. Databricks documents this exact case: 12.0 == 12 is false. Fixes are to set the value as the integer 2 or to use a numeric comparison. Task values are available within the run, keep their JSON form, and are valid condition operands.

How to reason it out
  1. Note the value was set as a float, 2.0.
  2. Recall that == and != compare as strings in condition tasks.
  3. Compare the strings 2.0 and 2: not equal, so the false branch runs.
  4. Fix by setting an integer or using a numeric operator.

Exam tip: Condition tasks: == and != are string comparisons; >, >=, <, <= are numeric.

Lakeflow Jobs Tasks, Dependencies and Control Flow: Retries, Run If, If/Else and For Each (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 17Working with Lakeflow Jobs

A data engineer must run the same ingestion notebook for each of 40 country codes. Each country must appear as its own run in the job, so that a failure for one country is visible and can be fixed without hiding the others. The engineer does not want to define 40 separate tasks. Which approach should they use?

Choose one.

  • a
    An If/else condition task that checks each country code and routes it to the ingestion notebook

    If/else chooses between two branches once; it does not repeat a task for many values.

  • b
    A For each task with the country codes as inputs and a nested notebook task that reads {{input}} Correct

    Correct. For each runs the nested notebook once per input value and tracks every iteration separately.

  • c
    A single notebook task whose Python code loops through the 40 country codes one after another

    This works functionally, but all countries share one task run, so a single failure is not isolated per country.

  • d
    A Run Job task that triggers the ingestion job once, passing the 40 country codes as one parameter

    One child run still processes every country together, so failures are not tracked per country.

The concept

The For each task loops a nested task over an array of inputs, one iteration per value.

Why that’s the answer

Looping is the For each task's job. Its inputs are a JSON array such as ["US", "DE", ...], and the nested notebook task receives the current value through {{input}}. Each iteration is tracked on its own, which meets the per-country visibility requirement. A loop inside one notebook runs as a single task, and If/else or a Run Job task does not repeat work per value.

How to reason it out
  1. Recognise a loop: the same task once per value.
  2. Recall the For each task and its JSON array of inputs.
  3. Pass the current value to the nested task with {{input}}.
  4. Reject single-run designs that hide per-country failures.

Exam tip: Repeat a task per value with For each; reference the current value with {{input}}.

Lakeflow Jobs Tasks, Dependencies and Control Flow: Retries, Run If, If/Else and For Each (Databricks Data Engineer Associate) — the lesson that teaches this.

Domain 5: Implementing CI/CD

10% of the Databricks DEA exam, so 2 of the 25 questions on this page.

Question 18Implementing CI/CD

A data engineer's branch spike-cdc holds a week of failed experiments that were already pushed. They want spike-cdc to match main exactly again, dropping both the local and the remote experimental commits, and nobody else uses the branch. Which Git folder operation does this?

Choose one.

  • a
    Reset spike-cdc to main Correct

    Correct. Reset performs a hard reset and a force push, so the branch matches main locally and remotely.

  • b
    Merge main into spike-cdc

    A merge adds main's commits but keeps every experimental commit on the branch.

  • c
    Pull main into spike-cdc

    Pull updates the current branch from its own remote; it removes nothing.

  • d
    Rebase spike-cdc onto main

    A rebase replays the experimental commits on top of main, so they stay on the branch.

The concept

Reset in a Git folder is git reset --hard followed by git push --force.

Why that’s the answer

The requirement is to discard committed and pushed work. Reset is the only operation that does that: it hard-resets the branch to the chosen branch and force-pushes, discarding commits locally and remotely. Merge and rebase keep the commits, and pull only adds remote changes. Because it is destructive, reset suits a branch nobody else depends on.

How to reason it out
  1. Note the requirement: drop pushed commits on both sides.
  2. Recall that merge, pull and rebase all keep commits.
  3. Recall that reset is a hard reset plus force push.
  4. Use reset on a branch nobody else depends on.

Exam tip: Git folder Reset = hard reset + force push: it discards local and remote commits.

Databricks CI/CD: Git Folders, Declarative Automation Bundles and the Databricks CLI (Data Engineer Associate) — the lesson that teaches this.

Question 19Implementing CI/CD

A data team manages three Lakeflow jobs and a Lakeflow Spark Declarative Pipeline by clicking through the UI in separate dev, test and prod workspaces, and the copies keep drifting. They want the definitions kept as source-controlled files and deployed the same way to every workspace. What should they adopt?

Choose one.

  • a
    Git folders in each workspace with main checked out, pulled after each merge to deploy

    Git folders sync code files, but the job and pipeline definitions would still be clicked together separately in each workspace.

  • b
    Declarative Automation Bundles, deployed to each workspace with the Databricks CLI Correct

    Correct. Bundles describe jobs, pipelines and other assets as YAML plus code, and the CLI deploys the same bundle to each target workspace.

  • c
    Job JSON and Declarative Pipeline settings copied from dev into test and prod by hand

    Copying JSON by hand is the same drift-prone manual process, just with an extra export step.

  • d
    Workspace folders exported with the CLI and imported to deploy them in test and prod

    Workspace export and import moves notebooks and files, not the job and pipeline definitions themselves.

The concept

Declarative Automation Bundles (formerly Databricks Asset Bundles) define jobs, pipelines and other assets as source files for repeatable deployment.

Why that’s the answer

Databricks recommends bundles for CI/CD: resources live in YAML next to the code, under source control, and the CLI deploys them to each target. Git folders and workspace export move code, but not the job and pipeline definitions, and copying JSON by hand reproduces the drift.

How to reason it out
  1. Note the need: definitions as files, deployed identically.
  2. Recall what bundles package: resources plus code.
  3. Recall that the CLI deploys a bundle to each target.
  4. Reject approaches that only move code or rely on manual copies.

Exam tip: Jobs and pipelines as code, promoted across environments: use bundles.

Databricks CI/CD: Git Folders, Declarative Automation Bundles and the Databricks CLI (Data Engineer Associate) — the lesson that teaches this.

Domain 6: Troubleshooting, Monitoring, and Optimization

10% of the Databricks DEA exam, so 2 of the 25 questions on this page.

Question 20Troubleshooting, Monitoring, and Optimization

On Monday, an on-call data engineer sees that many different jobs in the workspace failed over the weekend. Before opening individual jobs, the engineer wants the most frequent error types across those failures and a list of the failed runs with one error code, without writing SQL. Where should the engineer start?

Choose one.

  • a
    The Jobs list, opening each failed job's matrix view and reading each red task's error

    This works job by job and does not summarize error types across the workspace, which is what the engineer wants first.

  • b
    The system.lakeflow.job_run_timeline table, counting error types per termination code

    The system table can answer this, but it requires writing SQL, which the stated constraint rules out.

  • c
    The compute event log of each job cluster, filtered to the weekend's run termination events

    Compute event logs cover cluster lifecycle, cluster by cluster. They do not group job run failures by error type.

  • d
    The Runs tab under Jobs & Pipelines, using its Top 5 error types and its error-code filter Correct

    Correct. The workspace Runs tab lists runs from all jobs, can filter by status and error code, and shows a Top 5 error types table for the selected time range.

The concept

The workspace-wide Runs tab under Jobs & Pipelines lists runs across jobs, filters by status and error code, and shows the Top 5 error types.

Why that’s the answer

The engineer wants a cross-job summary with no SQL. The Runs tab under Jobs & Pipelines covers all jobs in the workspace, filters by status, time range and error code, and shows a Top 5 error types table. The job_run_timeline system table holds similar data but needs a query, which the constraint excludes; per-job matrix views and cluster event logs do not summarize across jobs.

How to reason it out
  1. Note the scope: many jobs, summarized, no SQL.
  2. Recall the workspace-wide Runs tab and its filters.
  3. Use Top 5 error types and the error-code filter.
  4. Reject per-job views and the SQL option.

Exam tip: Many jobs failing? Start at the workspace Runs tab: Top 5 error types and filters.

Monitoring, Troubleshooting and Optimizing Pipelines: Lakeflow Jobs Run History, Spark UI, Liquid Clustering and Predictive Optimization (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 21Troubleshooting, Monitoring, and Optimization

A join stage in the Spark UI has 200 tasks. 199 tasks finish in about 20 seconds each, while one task runs for 25 minutes and processes far more shuffle data than the rest. The other stages of the job look normal. What does this pattern most likely indicate?

Choose one.

  • a
    Too many shuffle partitions, so scheduling overhead outweighs the data in each task

    Too many partitions makes many tasks tiny and adds overhead, but it would not make one task read far more data than the others.

  • b
    General disk spill, because the executors lack memory for the stage's data

    General spill affects most tasks of the stage evenly. One outlier task with far more data points elsewhere.

  • c
    An executor lost during the stage, so its task was retried and ran a second time

    A retried task restarts the same partition; it would not read many times more shuffle data than its peers.

  • d
    Skew, with one key's partition holding many more rows than its peer partitions Correct

    Correct. One task taking much longer and reading much more data than the others in the same stage is the signature of skew: one partition, usually one hot key, is much larger.

The concept

Skew shows as a few tasks in a stage taking far longer, and reading far more data, than the rest.

Why that’s the answer

Tasks in a stage do the same work on different partitions, so their times should be close. When one task reads far more shuffle data and runs far longer, its partition is oversized, typically because one join key holds a large share of the rows. Too many partitions, general spill and executor loss produce different patterns.

How to reason it out
  1. Compare the outlier task with its peers in the same stage.
  2. Note it reads much more data, not just runs longer.
  3. Conclude one partition is oversized: data skew.
  4. Reject causes that affect tasks evenly.

Exam tip: One task far slower and far bigger than its stage-mates = skew.

Monitoring, Troubleshooting and Optimizing Pipelines: Lakeflow Jobs Run History, Spark UI, Liquid Clustering and Predictive Optimization (Databricks Data Engineer Associate) — the lesson that teaches this.

Domain 7: Governance and Security

15% of the Databricks DEA exam, so 4 of the 25 questions on this page.

Question 22Governance and Security

The external Delta table main.sales.orders is owned by the service principal sp-ingest. A data engineer, who holds MANAGE on the table, runs ALTER TABLE main.sales.orders SET MANAGED on a cluster with Databricks Runtime 15.4 LTS, and it fails. The table must keep its name, history and grants. How should the conversion be run?

Choose one.

  • a
    Run SET MANAGED as sp-ingest on serverless compute Correct

    Correct. SET MANAGED requires the table owner and serverless compute or Databricks Runtime 17.3 LTS or above; running as sp-ingest on serverless meets both.

  • b
    Run SET MANAGED as the engineer on a 17.3 LTS cluster

    The runtime is now new enough, but the engineer is still not the owner, and MANAGE does not satisfy the ownership requirement for SET MANAGED.

  • c
    Make the engineer the owner, then rerun on the 15.4 cluster

    Ownership is fixed, but SET MANAGED still needs serverless compute or Databricks Runtime 17.3 LTS or above, so it fails again on 15.4 LTS.

  • d
    Run a CTAS into a new managed table as sp-ingest on 15.4

    CTAS creates a different table with no history and no grants, which breaks the stated requirements.

The concept

ALTER TABLE ... SET MANAGED converts an external Delta table in place; it needs the owner and a recent runtime.

Why that’s the answer

Two conditions failed at once: the engineer is not the owner (MANAGE is not sufficient for SET MANAGED) and Runtime 15.4 LTS is too old (serverless or 17.3 LTS and above is required). Running as the owning service principal on serverless meets both and keeps the name, history and grants. Moving to a newer runtime without ownership, or taking ownership while staying on 15.4 LTS, each fixes only one condition, and CTAS loses history and grants.

How to reason it out
  1. Recall that SET MANAGED requires table ownership.
  2. Recall that it needs serverless or Runtime 17.3 LTS+.
  3. Check each option against both conditions.
  4. Reject CTAS because history and grants must be kept.

Exam tip: SET MANAGED: run it as the owner, on serverless or 17.3 LTS+.

Unity Catalog Managed vs External Tables, GRANT, REVOKE and DENY (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 23Governance and Security

A team wants its external Delta table main.finance.ledger to become a Unity Catalog managed table so it benefits from predictive optimization. Dashboards and jobs reference the table by name, and its history and existing grants must be kept. Writers can tolerate a pause of a few minutes. Which approach should the data engineer use?

Choose one.

  • a
    CTAS into a new managed table, then swap the table names

    A CTAS copy starts a new history and carries none of the grants, so both must-keep items are lost.

  • b
    ALTER TABLE main.finance.ledger SET MANAGED Correct

    Correct. SET MANAGED copies the data into managed storage and keeps the table's name, history, settings and permissions, with only a brief pause for writers.

  • c
    DEEP CLONE into a new managed table, then swap the names

    A deep clone is a new table: grants are not copied, and the name swap still means dropping the original.

  • d
    ALTER TABLE main.finance.ledger SET TBLPROPERTIES for auto optimize

    Table properties tune writes but leave the table external, so it never becomes eligible for managed-table features such as predictive optimization.

The concept

SET MANAGED converts an external table to managed in place, keeping name, history and permissions.

Why that’s the answer

SET MANAGED is built for this: it copies the files and log into managed storage, keeps the name, settings, permissions, views and history, and only briefly blocks writers. A CTAS copy and a deep clone both create new tables that do not carry the grants, and changing table properties leaves the table external.

How to reason it out
  1. Note what must be kept: name, history, grants.
  2. Recall that SET MANAGED converts in place and keeps them.
  3. Reject copies that create new tables.
  4. Reject property changes that leave the table external.

Exam tip: External to managed, keeping everything: ALTER TABLE ... SET MANAGED.

Unity Catalog Managed vs External Tables, GRANT, REVOKE and DENY (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 24Governance and Security

Five days ago a data engineer converted the external table main.ops.events to managed with SET MANAGED. Since then jobs have written to it every hour. A reader the team cannot upgrade has stopped working since the conversion, so the table must go back to being external without losing the writes made since. What should the engineer do?

Choose one.

  • a
    Run RESTORE TABLE main.ops.events to its pre-conversion version

    RESTORE rolls the data back to that version, discarding five days of writes, and the table stays managed.

  • b
    Run ALTER TABLE main.ops.events UNSET MANAGED Correct

    Correct. UNSET MANAGED rolls back a conversion within 14 days and keeps the writes made to the managed location since then.

  • c
    Re-create an external table on the old path, then drop the managed one

    The old path does not contain the writes made after conversion, so they would be lost.

  • d
    Run UNDROP TABLE main.ops.events to bring back the external table

    Nothing was dropped. SET MANAGED converts the table in place, so there is no dropped external table to undrop.

The concept

UNSET MANAGED reverses a SET MANAGED conversion within 14 days.

Why that’s the answer

A table converted with SET MANAGED can be rolled back with UNSET MANAGED within 14 days, on serverless or Runtime 17.3 LTS or above. The rollback keeps writes made after the conversion. RESTORE would discard those writes and keep the table managed, the old path is missing the new data, and UNDROP is for dropped tables.

How to reason it out
  1. Note it was converted with SET MANAGED five days ago.
  2. Recall the 14-day UNSET MANAGED rollback.
  3. Check that post-conversion writes are kept.
  4. Reject options that lose writes or target dropped tables.

Exam tip: Undo a SET MANAGED within 14 days with UNSET MANAGED.

Unity Catalog Managed vs External Tables, GRANT, REVOKE and DENY (Databricks Data Engineer Associate) — the lesson that teaches this.

Question 25Governance and Security

A data engineer plans ALTER TABLE ... SET MANAGED on the external table main.sales.orders. A Structured Streaming job reads the table continuously, and it is shared through Databricks-to-Databricks Delta Sharing with a partner workspace. The partner must keep receiving data after the change. Which follow-up work does the conversion need?

Choose one.

  • a
    Restart the streaming job and re-grant SELECT on the table to readers

    The stream is handled, but grants survive the conversion so re-granting does nothing, and the share still points at the old location until it is reshared.

  • b
    Restart the streaming job and reshare the table with the recipient Correct

    Correct. Streaming jobs must be restarted after the conversion, and Databricks-to-Databricks recipients keep reading the old location until the table is reshared.

  • c
    Reshare the table and recreate the views that reference the table

    The share is handled, but views survive the conversion unchanged, and the streaming job still fails until it is restarted.

  • d
    Recreate the views that reference it and re-grant SELECT to readers

    Views and grants are both kept by SET MANAGED, so this work is wasted, while the stream and the share are left broken.

The concept

SET MANAGED keeps a table's identity, but streams and Databricks-to-Databricks shares need follow-up.

Why that’s the answer

The conversion keeps the table's name, history, permissions and dependent views, so re-granting SELECT or recreating views is unnecessary work. Two documented limitations do need follow-up: existing streaming jobs fail and must be restarted, and Databricks-to-Databricks sharing keeps pointing at the old location until the table is reshared. Only the option that restarts the stream and reshares the table covers both, without busywork on things the conversion preserves.

How to reason it out
  1. List the consumers: a stream and a Databricks-to-Databricks share.
  2. Recall what SET MANAGED keeps: name, history, grants and views.
  3. Recall what it does not handle: running streams and Databricks-to-Databricks shares.
  4. Choose the option that restarts the stream and reshares the table.

Exam tip: After SET MANAGED: restart streams and reshare Databricks-to-Databricks shares.

Unity Catalog Managed vs External Tables, GRANT, REVOKE and DENY (Databricks Data Engineer Associate) — the lesson that teaches this.

Keep going with Databricks DEA

Databricks DEA practice by domain

Databricks DEA sample questions: your questions

No. Real exam questions are confidential. These are original questions written to the skills in the official Databricks DEA exam guide, so they test the same knowledge in the same style without being copies of the exam.

Source

The domains and weights on this page come from the official Databricks DEA exam guide.