Home / Practice tests / DE Professional

Free · No credit card required

Databricks Data Engineer Professional Practice Test

Realistic professional-level practice questions with worked explanations — Lakeflow Spark Declarative Pipelines, streaming CDC, performance tuning, Unity Catalog governance, and Asset Bundles.

60 questions on the real exam
120 min time limit
$200 per exam attempt

Exam blueprint

What's on the exam

The exam sections with their official weights — focus your study time where the points are.

Developing Code for Data Processing using Python and SQL

22%

Lakeflow Spark Declarative Pipelines, streaming tables vs. materialized views, AUTO CDC, advanced PySpark and SQL patterns.

Cost & Performance Optimisation

13%

Spark UI diagnosis, join strategies and skew, OPTIMIZE, liquid clustering, cluster sizing and cost control.

Monitoring and Alerting

10%

System tables, SQL alerts, job notifications, pipeline event logs and streaming metrics.

Ensuring Data Security and Compliance

10%

Column masks, row filters, GDPR delete patterns, skipChangeCommits, secret management.

Debugging and Deploying

10%

Asset Bundles, repair runs, CI/CD promotion across environments, task dependencies.

Data Transformation, Cleansing, and Quality

10%

Expectations, deduplication, quarantine patterns, MERGE-based upserts.

Data Ingestion & Acquisition

7%

Auto Loader at scale, COPY INTO, Lakeflow Connect, streaming checkpoints.

Data Governance

7%

Unity Catalog privileges and inheritance, tags, BROWSE, discovery.

Data Modelling

6%

Star schemas, slowly changing dimensions, liquid clustering vs. partitioning vs. Z-order.

Data Sharing and Federation

5%

Delta Sharing, recipients and shares, Lakehouse Federation connections and foreign catalogs.

Straight from our question bank

Try 7 real practice questions

Every question comes with a worked explanation — expand the answer when you're ready.

1 Developing Code for Data Processing using Python and SQL

A data engineering team has an existing production Spark Structured Streaming job written in PySpark that reads from Delta Lake, applies a stateful sessionization window function using flatMapGroupsWithState, and writes results to a Gold Delta table. The team is evaluating migrating this job to Lakeflow Spark Declarative Pipelines. A senior engineer raises concerns about whether Lakeflow SDP can support all the features required. Which statement MOST accurately describes the capabilities and limitations of Lakeflow SDP compared to the team's direct Structured Streaming job for this specific use case?

  1. ALakeflow SDP can fully replace the direct Structured Streaming job because it executes all pipeline code on the same Spark Structured Streaming engine. flatMapGroupsWithState can be used inside a @dlt.table decorated function by wrapping the streaming DataFrame operation before returning the result DataFrame. The SDP framework passes the raw streaming DataFrame to the function, allowing arbitrary Spark Structured Streaming operations.
  2. BBoth approaches are equivalent in capability, but direct Structured Streaming is always preferable for production workloads because Lakeflow SDP adds unnecessary management overhead (pipeline metadata, event logging, Unity Catalog lineage) that increases query latency by 15–30% compared to an equivalent direct Structured Streaming job with the same transformations.
  3. CLakeflow SDP is strictly more capable than direct Structured Streaming because it runs on a newer, proprietary streaming engine built by Databricks that has replaced Spark Structured Streaming internally. All Structured Streaming operators, including flatMapGroupsWithState, are available in Lakeflow SDP and execute with better performance due to the optimized runtime. Migrating to Lakeflow SDP is always recommended for any streaming workload.
  4. DThe team can migrate to Lakeflow SDP by declaring the Gold table as a Streaming Table and using APPLY CHANGES INTO with a custom SQL SEQUENCE BY expression that replicates the sessionization logic. APPLY CHANGES supports arbitrary windowing functions in its SEQUENCE BY clause, making it a suitable replacement for flatMapGroupsWithState in sessionization use cases.
  5. ELakeflow SDP does not natively support flatMapGroupsWithState or other arbitrary stateful Structured Streaming operators within its declarative table definitions. Lakeflow SDP is designed for standard SQL-expressible transformations and common streaming patterns (APPLY CHANGES, aggregations, joins). For workloads requiring custom stateful operator logic like flatMapGroupsWithState, direct Spark Structured Streaming (via the DataFrame API in a regular Python/Scala job) remains the more appropriate choice because it gives full access to all Structured Streaming operators without the constraints of the declarative pipeline framework.
Show answer & explanation

Correct answer: E

WHY E: This is the accurate and honest assessment. Lakeflow SDP is built on Spark Structured Streaming and handles the vast majority of streaming ETL patterns extremely well — but it is a declarative framework that constrains table definitions to SQL-expressible or DataFrame API patterns that fit its table update model. flatMapGroupsWithState is a low-level stateful operator that manages arbitrary per-key state across micro-batches using a custom user-defined state transition function. This type of arbitrary stateful processing does not map cleanly to Lakeflow SDP's Streaming Table or Materialized View constructs. For such cases, direct Structured Streaming gives the team full control over all streaming operators. The correct guidance is to use Lakeflow SDP for the majority of pipeline logic and fall back to direct Structured Streaming when custom stateful operators are required. WHY NOT A: While @dlt.table functions do receive a streaming DataFrame, Lakeflow SDP's framework imposes constraints on what operators can be applied — arbitrary stateful operators like flatMapGroupsWithState are not supported within the declarative pipeline execution model. WHY NOT C: Lakeflow SDP is not a replacement streaming engine — it runs on top of Spark Structured Streaming. It does not replace SSA internally, and flatMapGroupsWithState is not available within pipeline table definitions. WHY NOT D: APPLY CHANGES INTO is for CDC (insert/update/delete from a change stream), not for arbitrary sessionization window logic. The SEQUENCE BY clause determines event ordering for CDC operations, not custom stateful window computations. WHY NOT B: Lakeflow SDP's management overhead does not add 15–30% query latency. The metadata and lineage operations are asynchronous and do not block query execution paths.

2 Cost & Performance Optimisation

A data engineer is optimizing a 10 TB Unity Catalog managed Delta table storing e-commerce events. Queries frequently filter on user_id (100 million distinct values) and event_type (12 distinct values). The table was created without any explicit file layout optimization. The Spark UI shows queries scanning all 2,000 data files even with highly selective WHERE user_id = '...' filter clauses. Which combination of actions correctly diagnoses the root cause and applies the most effective optimization?

  1. AThe root cause is that Delta Lake does not maintain statistics for columns with more than 1,000 distinct values. Solution: partition on event_type (low cardinality) and set spark.sql.shuffle.partitions=200 for query-level parallelism.
  2. BThe root cause is that without any data layout optimization, high-cardinality user_id values are scattered randomly across all files — even though per-file min/max statistics are collected, every file's range includes the target value, so no file can be skipped. Solution: run OPTIMIZE ... ZORDER BY (user_id, event_type) to co-locate similar user_id values within fewer files, tightening per-file min/max ranges and enabling data skipping to prune most files.
  3. CThe root cause is that data skipping in Delta Lake only works for partitioned columns. Since neither user_id nor event_type is a partition key, Delta skips no files. Solution: partition the table by user_id using range partitioning to enable partition pruning.
  4. DThe root cause is that the table requires explicit ANALYZE TABLE ... COMPUTE STATISTICS FOR COLUMNS user_id, event_type before any data skipping can occur — Delta Lake never collects statistics automatically. Solution: run ANALYZE and then queries will use data skipping without any layout changes.
  5. EThe root cause is that Spark UI showing all files scanned indicates the query is not using predicate pushdown. Solution: switch from the PySpark DataFrame API to Spark SQL string queries, which support predicate pushdown while DataFrame operations do not.
Show answer & explanation

Correct answer: B

WHY B: Delta Lake's data skipping works by reading per-file column statistics (min, max, null count, row count) that are collected automatically when data is written. For a high-cardinality column like user_id with random insertion order, values are spread across all files. Every file's min-max range overlaps with any specific target user_id value — so no file can be avoided by the statistics-based skip. OPTIMIZE ... ZORDER BY (user_id) co-locates records with similar user_id values into the same set of files, dramatically tightening per-file min-max ranges. After ZORDER, a query for a specific user_id finds that most files' ranges don't include the target value and skips them. Adding event_type to ZORDER further prunes on that filter. WHY NOT A: Delta Lake does NOT have a cardinality limit for statistics collection — statistics are collected on the first 32 columns by default regardless of cardinality. Partitioning on low-cardinality event_type (12 values) would create only 12 partitions and would not help prune on user_id selectivity. WHY NOT C: Data skipping is NOT limited to partitioned columns. Delta Lake collects min/max statistics on all data columns (up to 32 by default), and data skipping uses these statistics for file pruning on any filtered column — partition or not. WHY NOT D: For Unity Catalog managed tables, Databricks automatically collects statistics via predictive optimization. Statistics ARE collected automatically. The root issue is data layout (scattered user_id values), not missing statistics. WHY NOT E: Predicate pushdown works identically for both Spark SQL and PySpark DataFrame API — both generate the same query plan with filters pushed to the scan node. The API choice does not affect predicate pushdown or data skipping behavior.

3 Monitoring and Alerting

A user opens Query History and clicks a query, but the Query Profile option is missing. Which explanation is most consistent with the documented behavior of query profiles?

  1. AQuery Profile is available only for queries executed from notebooks, not from SQL Warehouses.
  2. BQuery Profile requires enabling Change Data Feed on every table referenced by the query.
  3. CQuery Profile is not available if the query result was served from the query cache.
  4. DQuery Profile is available only to workspace admins, regardless of warehouse permissions.
Show answer & explanation

Correct answer: C

WHY C: Databricks documents that a query profile is not generated/available when a query is served from the query cache. WHY NOT A: Query profiles are available for SQL workloads (and can be accessed from Query History, SQL editor, notebooks, and pipeline-related UIs). WHY NOT B: CDF is unrelated to query profiling. WHY NOT D: Access is not admin-only; it’s tied to the query context and (for SQL warehouses) appropriate permissions such as ownership or CAN MONITOR.

4 Data Modelling

A data engineer is designing a star schema for a large analytical workload in Databricks. The central fact table fact_orders (500 GB, growing ~5 GB/day) is joined frequently with dim_product (10 MB) and dim_customer (200 MB) on product_id and customer_id respectively. Analysts filter primarily by order_date and product_category. Which combination of design decisions BEST optimizes query performance for this star schema?

  1. APartition fact_orders by product_id and customer_id to enable partition pruning on the join keys used with both dimension tables.
  2. BPartition fact_orders by product_id (high cardinality) and use ZORDER BY (order_date, product_category) since ZORDER handles all filter columns equally regardless of cardinality.
  3. CPartition fact_orders by order_date and apply CLUSTER BY (product_category) — partitioning and liquid clustering can be combined on the same table for complementary optimization.
  4. DApply liquid clustering on fact_orders with CLUSTER BY (order_date, product_category) to optimize for the primary query filters; dim_product and dim_customer are small enough to be broadcast-joined automatically by Spark without additional layout optimization.
Show answer & explanation

Correct answer: D

WHY D is correct: This option correctly applies two complementary best practices: (1) Liquid clustering on fact_orders with CLUSTER BY (order_date, product_category) physically co-locates records sharing the same date and product category, enabling data skipping when analysts filter by these columns. Liquid clustering is the Databricks-recommended layout for large fact tables with growing data and analytical query patterns. (2) dim_product (10 MB) and dim_customer (200 MB) are both small enough to fall within Spark's automatic broadcast join threshold. Spark automatically broadcasts tables below spark.sql.autoBroadcastJoinThreshold (default 10 MB; commonly tuned up to 100–200 MB for dimension tables), eliminating shuffle-based joins entirely. Small dimension tables in star schemas typically need no special layout optimization — their size advantage is leveraged by broadcast joins. WHY NOT A: Partitioning fact_orders by product_id and customer_id is a severe anti-pattern for multiple reasons. Both columns are high cardinality (potentially millions of distinct values), which would create millions of tiny partitions — the exact scenario Databricks documentation warns against: 'Tables where a typical partition key could leave the table with too many or too few partitions' are not suited to partitioning. Additionally, join operations on dimension foreign keys are served by broadcast joins on small dimension tables, not by partition pruning on the fact table. WHY NOT B: Partitioning by product_id (high cardinality) would create too many partitions for the same reasons described above. Additionally, while ZORDER can handle high-cardinality columns, Databricks now recommends liquid clustering over ZORDER for all new tables. ZORDER is also constrained to operate within each partition's boundary — on an over-partitioned table by product_id, ZORDER on order_date cannot combine files across different product partitions. WHY NOT C: Liquid clustering and Hive-style partitioning cannot be combined on the same Delta table. The documentation explicitly states: 'Clustering is not compatible with partitioning or ZORDER.' You can enable liquid clustering only on unpartitioned tables (ALTER TABLE ... CLUSTER BY requires the table to be unpartitioned). Attempting to apply both would result in an error.

5 Data Sharing and Federation

You need to share a Unity Catalog-managed dataset with another organization that also uses a Unity Catalog-enabled Databricks workspace. You also want to share a notebook and a Unity Catalog volume along with the tables, and you do not want to manage long-lived bearer tokens for the recipient. Which Delta Sharing model best fits these requirements?

  1. AOpen Delta Sharing (D2O) using bearer tokens, because it supports notebooks and volume sharing and avoids token management.
  2. BDatabricks-to-Databricks (D2D) Delta Sharing, because it supports sharing tables plus notebooks/volumes/models and does not require token-based credentials for the recipient.
  3. CCustomer-managed open-source Delta Sharing server, because it is required for any Databricks-to-Databricks sharing and provides the best performance.
  4. DUnity Catalog cross-workspace permissions, because Delta Sharing is only for non-Databricks recipients.
Show answer & explanation

Correct answer: B

WHY B: Databricks-to-Databricks Delta Sharing is designed for sharing between Unity Catalog-enabled Databricks workspaces (often across accounts/clouds). It supports assets not available in open sharing (for example notebook files and Unity Catalog volumes) and avoids provider-managed bearer tokens by using the Databricks-managed identity/sharing identifier flow. WHY NOT A: Open sharing (D2O) is for recipients on any platform, but it typically uses bearer tokens or OIDC federation and does not support notebook/volume/model sharing. WHY NOT C: The open-source server is for customer-managed implementations and is not required for D2D on Databricks. WHY NOT D: If both workspaces are attached to the same Unity Catalog metastore, you can govern access with Unity Catalog directly, but the scenario describes sharing across organizations/metastores and explicitly includes Delta Sharing-specific assets.

6 Ensuring Data Security and Compliance

A security engineer is applying column masks to a Unity Catalog table. Which of the following statements correctly describes the constraints on column masks?

  1. AA column can have multiple masks applied simultaneously, all of which are evaluated in the order they were added.
  2. BEach column can have at most one column mask, and the mask function must return the same data type as the masked column.
  3. CA column mask is defined as a Python UDF and must be stored in the same schema as the table.
  4. DColumn masks can be applied to views as well as base tables, allowing centralized masking logic.
  5. EColumn masks work with all Databricks Runtime versions, including those below 12.2 LTS, where data is returned in plain text.
Show answer & explanation

Correct answer: B

WHY B is correct: Unity Catalog enforces two strict rules for column masks: (1) each column can have at most ONE mask function assigned at any time — attempting to add a second mask to the same column is an error; (2) the SQL UDF used as the mask must return the same data type as the column being masked. This prevents type coercion issues at query time. WHY NOT A: Multiple masks per column are NOT allowed. Only a single mask function can be active on a column at any time. WHY NOT C: Column masks are defined as SQL UDFs, not Python UDFs. While the UDF can reside in any schema the user has permission to access, it does not have to be in the same schema as the table. WHY NOT D: Column masks cannot be applied to views. They are a table-level feature and apply to base tables only. WHY NOT E: On Databricks Runtime versions below 12.2 LTS, access to tables with row filters or column masks fails securely — the query returns NO data rather than exposing plain text. This is the opposite of what is described.

7 Data Ingestion & Acquisition

A data engineer must build an append-only ingestion pipeline that lands raw events from a message bus into a Delta Bronze table. The pipeline is a Structured Streaming job that must be able to fail and be restarted at any time without producing duplicate rows in the Bronze table, and it must not require a downstream deduplication step. The source provides an at-least-once delivery guarantee. Which combination of mechanisms provides exactly-once append semantics for the Bronze write under restarts?

  1. AWrite with .mode('append') in a foreachBatch and, inside the batch function, run a DELETE on the Bronze table for the current batch's key range before inserting, so each restart cleans up any partial prior write. This makes the append idempotent because the delete-then-insert pair is atomic per batch.
  2. BUse a Structured Streaming write to the Delta table with a configured checkpointLocation. Delta's streaming sink records each committed batch id in its transaction log, so on restart Delta skips micro-batches that were already committed, giving exactly-once appends without a manual dedup step.
  3. CSet the Delta table property delta.enableChangeDataFeed to true and write in complete output mode. Change Data Feed tracks every committed version, so on restart the sink replays only the uncommitted deltas, guaranteeing no duplicate rows are appended.
  4. DAdd .option('txnAppId', 'bronze').option('txnVersion', current_timestamp()) to the streaming write. The txnVersion derived from the current timestamp guarantees a unique transaction id per batch so that Delta rejects any replayed write with an older timestamp.
  5. EEnable spark.databricks.delta.autoCompact and optimizeWrite, then write in append mode without a checkpoint. Auto-compaction rewrites duplicate rows into a single file during ingestion, so restarts that re-append the same records are automatically collapsed to one copy.
Show answer & explanation

Correct answer: B

WHY B: A Structured Streaming write to a Delta sink with a persistent checkpointLocation gives exactly-once semantics: Delta's transaction log durably records the highest committed streaming batch id, so when the job restarts it does not re-commit an already-committed micro-batch, and it resumes source offsets from the checkpoint. No downstream dedup is needed. WHY NOT A: Delete-then-insert per batch is not generally atomic against arbitrary key ranges for append-only raw events (there may be no clean key range), adds heavy rewrite cost, and is unnecessary given Delta's built-in idempotent streaming commits. WHY NOT C: complete output mode rewrites the whole result each batch (used for aggregations), which is wrong for append-only raw ingestion, and Change Data Feed tracks row changes for consumers — it does not provide the sink's restart idempotency. WHY NOT D: The txnAppId/txnVersion idempotent-write API is designed for batch writers using a monotonically increasing version per source; deriving txnVersion from a timestamp is not the documented pattern and streaming already handles this via the checkpoint. WHY NOT E: Auto-compaction only rewrites small files into larger ones; it does not detect or remove duplicate rows, and writing a stream without a checkpoint loses exactly-once guarantees entirely.

Take the full practice test free →

Why it works

Practice tests beat re-reading the docs

Find your weak spots in 20 minutes instead of 20 hours.

Take a timed test

Full-length, under exam conditions — no signup needed to try.

See your breakdown

Score plus a topic-by-topic analysis of where you lost points.

Study what matters

Focus on your two or three weakest areas — every explanation teaches the concept.

Retake until ready

Consistently above 80%? You're ready to book the real exam.

FAQ

Frequently asked questions


Is this Databricks Data Engineer Professional practice test free?

Yes. You can take a full-length Databricks Data Engineer Professional practice test on TestLogicHub without paying or entering a credit card.

How many questions are on the real Databricks Data Engineer Professional exam?

The exam has 60 multiple-choice questions and a 120-minute time limit. It costs USD 200 per attempt and is proctored.

What score do I need to pass?

Databricks does not publish an exact cut score. A safe target is to score consistently above 80% on full-length practice tests before booking the real exam.

Are these questions like the real exam?

The questions are mapped to the official exam guide sections, written in the scenario style of the real exam, and every answer comes with a full explanation.

Does TestLogicHub cover other Databricks certifications?

Yes — TestLogicHub has practice tests for the Databricks Data Engineer Associate and Professional, Data Analyst, Machine Learning Associate, and Generative AI Engineer certifications.

Ready to find your weak spots?

Take the free Databricks Data Engineer Professional practice test — timed, weighted, and explained like the real thing.

Start now — it's free →