Courseiva

CCNA Using Spark SQL Questions

52 questions · Using Spark SQL · All types, answers revealed

1
MCQhard

A developer is writing a Spark SQL query that must handle null values in a column named discount. The requirement is to replace null discounts with 0.0, but also to replace any negative discount values with 0.0, leaving positive values unchanged. Which expression should be used?

A.COALESCE(GREATEST(discount, 0.0), 0.0)
B.IF(discount < 0, 0.0, discount)
C.GREATEST(discount, 0.0)
D.COALESCE(discount, 0.0)
AnswerA

GREATEST(discount, 0.0) turns negative values into 0.0 but returns null if discount is null. Wrapping it with COALESCE(..., 0.0) replaces that null with 0.0. This combination satisfies both conditions: nulls become 0.0, negatives become 0.0, and positive values are preserved. It is the correct nested expression.

Why this answer

The requirement is to treat both nulls and negatives as zero. GREATEST(discount, 0.0) ensures negatives become 0.0 but yields null for null input. COALESCE then replaces that null with 0.0.

The nested expression COALESCE(GREATEST(discount, 0.0), 0.0) correctly handles both cases and leaves positive values untouched. Using COALESCE alone misses negatives, GREATEST alone misses nulls, and the IF expression misses nulls.

Exam trap

The trap here is forgetting that GREATEST returns null when any argument is null, so a separate COALESCE is needed to handle null inputs.

2
MCQmedium

When performing a join between a very small table and a massive table, which Spark SQL optimization technique should be applied to prevent a full shuffle?

A.Use the /*+ BROADCAST(small_table) */ hint.
B.Increase the shuffle partitions to 2000.
C.Enable the 'autoBroadcastJoinThreshold' to a very low value.
D.Convert the massive table into an unmanaged view.
AnswerA

The BROADCAST hint explicitly instructs the Spark optimizer to broadcast the smaller table to all worker nodes. This eliminates the need for a shuffle, which is the most expensive part of a join, and is a standard way to ensure high-performance execution in Spark SQL for asymmetric join operations.

Why this answer

Broadcasting is a critical optimization technique for star-schema joins. By sending a copy of the small table to every executor, Spark avoids the expensive shuffle phase associated with shuffling the massive table. This significantly reduces network I/O and latency.

For a Databricks developer, recognizing when to use hints or rely on the optimizer to perform broadcast joins is vital for writing performant, scalable SQL queries on large datasets.

Exam trap

Test-takers sometimes try to use partition pruning or caching hints instead of the specific broadcast hint required to eliminate shuffles during joins.

3
MCQeasy

Which SQL command is used to view the history of operations performed on a Delta table, including timestamps and operation types?

A.SHOW METADATA ON table_name
B.SELECT * FROM audit_log(table_name)
C.DESCRIBE HISTORY table_name
D.GET TABLE VERSION table_name
AnswerC

DESCRIBE HISTORY is the standard command for viewing the transaction log of a Delta table. It displays information such as the operation, user, timestamp, and version, which are critical for debugging and data lineage analysis. This command allows users to monitor table evolution and identify specific modifications.

Why this answer

The DESCRIBE HISTORY command is a core utility in Databricks for auditing and troubleshooting. It provides a detailed log of all modifications, including writes, updates, and deletes, along with version numbers. This is essential for understanding table evolution, debugging data pipelines, and implementing data governance.

Knowing this command is mandatory for any Spark developer responsible for maintaining and auditing production-level Delta Lake tables.

Exam trap

Test-takers often confuse DESCRIBE HISTORY with standard table description commands like DESCRIBE DETAIL or DESCRIBE TABLE, missing the temporal aspect of operations.

4
MCQhard

A developer is using Spark SQL to process a streaming DataFrame from a Kafka source. They need to perform a stateful operation that maintains state across micro-batches to count occurrences of each key over a sliding window of 10 minutes, sliding every 5 minutes. Which Spark SQL operation should they use?

A.Use the foreachBatch sink to manually maintain state in an external database.
B.Use groupBy with window('timestamp', '10 minutes', '5 minutes') and then count.
C.Use a tumbling window with window('timestamp', '10 minutes') and then count.
D.Use the dropDuplicates operator to remove duplicates within 10 minutes, then count.
AnswerB

Spark SQL structured streaming supports windowed aggregations using the window function. Specifying a window duration of 10 minutes and slide duration of 5 minutes creates overlapping windows. Grouping by the window and key, then counting, maintains state across micro-batches to produce counts per window. This is the correct approach for sliding window aggregations in structured streaming.

Why this answer

Structured streaming in Spark SQL supports windowed aggregations through the window function. Specifying a window duration and slide duration enables sliding windows. Grouping by the window and key, then applying an aggregation like count, maintains state across micro-batches and produces results for each window.

This is the built-in, fault-tolerant approach for stateful stream processing.

Exam trap

The trap here is confusing tumbling windows with sliding windows; tumbling windows do not overlap, while sliding windows require both window and slide durations.

5
MCQmedium

When performing a 'Z-ORDER' operation on a Delta table, how does it improve query performance?

A.It compresses data more tightly than standard Parquet compression.
B.It reorders data to maximize the effectiveness of data skipping.
C.It automatically creates a secondary index for every column in the table.
D.It removes all null values from the table to reduce storage size.
AnswerB

Z-Ordering rearranges data within files to ensure that related values are physically grouped together. This maximizes the probability that a query filter will result in skipping entire files, as the file-level statistics (min/max) become much more discriminative, directly reducing the total amount of data read from storage.

Why this answer

Z-Ordering is a technique that maps multi-dimensional data to one dimension while preserving locality. By co-locating related information in the same files, Z-Ordering enables the Delta Lake reader to skip more data when filtering. This is highly effective for high-cardinality columns, as it dramatically increases the effectiveness of data skipping, leading to significantly faster query response times in large, partitioned Delta tables.

Exam trap

Students often mistake Z-Ordering for standard partitioning or indexing, assuming it physically sorts the entire table into a single ordered sequence.

6
MCQmedium

You are optimizing a Spark SQL query that performs a large join between a 10GB table and a 5MB lookup table. To ensure performance efficiency, which command should you use to hint to the optimizer?

A.SELECT /*+ MERGE(t1, t2) */ * FROM t1 JOIN t2
B.SELECT /*+ SHUFFLE(t1, t2) */ * FROM t1 JOIN t2
C.SELECT /*+ BROADCAST(t2) */ * FROM t1 JOIN t2
D.SELECT /*+ SKEW(t1) */ * FROM t1 JOIN t2
AnswerC

The BROADCAST hint explicitly instructs the Spark catalyst optimizer to perform a broadcast hash join. By duplicating the smaller table to all executors, Spark eliminates the need for expensive wide transformations and data reshuffling, allowing the join to occur locally within each task, which maximizes performance for this specific scenario.

Why this answer

Spark SQL uses cost-based optimization, but small table broadcasts significantly reduce network shuffle overhead. By using the BROADCAST hint, you force the engine to send the small table to every executor, avoiding a full shuffle of the 10GB dataset. This is a critical optimization technique in Databricks environments where minimizing cross-node data movement is essential for reducing total job latency and improving cluster resource utilization.

Exam trap

Students frequently rely entirely on the Catalyst optimizer to catch small tables, forgetting that certain complex expressions prevent automatic broadcasting.

7
MCQhard

You are using Spark SQL to analyze a Delta table named transactions that is partitioned by a column region. You need to run a query that filters on region and also on a non-partitioned column amount. The table has statistics collected on region and amount. Which of the following best describes how Spark SQL will optimize the query?

A.Spark SQL will perform a full table scan because the filter on amount is not on a partition column, and then apply the filter after reading all data.
B.Spark SQL will use partition pruning based on the region filter and then apply data skipping on amount using the collected statistics to skip files where amount does not match the filter.
C.Spark SQL will dynamically repartition the data based on the amount filter to optimize the query, using adaptive query execution.
D.Spark SQL will only use partition pruning on region and will not use any statistics for amount because statistics are only collected on partition columns.
AnswerB

Spark SQL leverages partition pruning to eliminate entire partitions based on the region filter. Additionally, Delta Lake collects statistics on non-partitioned columns like amount, enabling data skipping at the file level. When statistics indicate that a file's min/max range for amount does not overlap with the filter, that file is skipped. This combination drastically reduces I/O.

Why this answer

Spark SQL uses partition pruning for the region filter and Delta Lake's data skipping for the amount filter, thanks to collected statistics. This minimizes the amount of data read. The other options incorrectly assume limitations or alternative optimizations.

Exam trap

The trap here is underestimating Delta Lake's data skipping capabilities on non-partition columns or confusing it with dynamic optimizations like AQE.

8
MCQmedium

You are querying a large Delta table partitioned by 'event_date'. You need to calculate the daily count of unique users, but the query is running slowly due to data skew on high-traffic dates. Which SQL approach effectively mitigates this skew during the aggregation?

A.Increase the 'spark.sql.shuffle.partitions' configuration to a significantly higher number.
B.Use the 'DISTINCT' keyword on all columns in the SELECT statement.
C.Add a new column with a random integer suffix to the grouping key, aggregate by the salted key, then aggregate again to remove the suffix.
D.Convert the table to a broadcast join using a dummy table.
AnswerC

Salting distributes the skewed data across multiple tasks by splitting the hot key into multiple sub-keys. This allows Spark to process the aggregation in parallel across different executors. A second aggregation stage is then required to sum the sub-totals, effectively removing the salt and providing the correct final count.

Why this answer

Salting the grouping key by appending a random integer suffix distributes the skewed keys across multiple partitions. By creating a temporary column that combines the original key with a random value, you ensure that the aggregation logic is parallelized across the cluster. This technique is essential in Spark SQL when a specific key value results in a task significantly larger than others, preventing straggler tasks from bottlenecking the entire job.

Exam trap

Examinees often forget the second aggregation step when implementing salting, leaving the random suffix attached to the final output data.

9
MCQmedium

Which of the following describes the behavior of a Delta table when a 'DELETE' operation is performed?

A.It deletes the entire table and recreates it without the target rows.
B.It physically removes the data from all files in a synchronous manner.
C.It identifies affected files, rewrites them excluding the target rows, and updates the transaction log.
D.It only marks the rows as deleted without affecting the underlying files.
AnswerC

Delta Lake uses a metadata-driven approach where it only processes the files containing the records to be deleted. By writing new files and updating the transaction log, it ensures ACID compliance and enables time travel, representing the efficient, performant way Delta Lake handles record-level deletions.

Why this answer

Delta Lake implements deletes by rewriting only the files containing the data to be removed, while maintaining a record of the change in the transaction log. This is much more efficient than traditional systems that might perform full table scans or require complex locking. Understanding this 'copy-on-write' or 'merge-on-read' approach is vital for Databricks developers to predict performance and costs when executing large-scale DML operations.

Exam trap

Candidates often assume DELETE drops the entire table or runs an instant metadata-only operation, forgetting that Delta Lake must physically rewrite the specific data files containing target rows.

10
MCQeasy

What is the purpose of the 'ANALYZE TABLE' command in Databricks?

A.To remove unused files and clean up storage.
B.To update the table schema after adding a column.
C.To generate statistics used by the optimizer for query planning.
D.To verify the integrity of the Delta log.
AnswerC

ANALYZE TABLE computes statistics like count, min, max, and null counts for columns. The cost-based optimizer uses this data to decide the best join strategy. This is a best practice in Databricks for any table that is frequently used in complex SQL queries to ensure optimal execution paths.

Why this answer

The ANALYZE TABLE command collects table statistics, such as row counts and column distributions. This information is crucial for the Spark Catalyst optimizer to make informed decisions about join strategies, such as when to broadcast a table or how to order joins. Without accurate statistics, the optimizer might choose inefficient execution plans, leading to degraded performance in complex multi-join queries.

Exam trap

Many test-takers think ANALYZE TABLE actually cleans up storage, optimizes file sizes, or runs data quality validation checks on the table.

11
MCQmedium

A data engineer must produce a report that shows each department's total salary, but only for departments where the total salary exceeds 500,000. The source DataFrame is created from a Delta table with columns department and salary. Which Spark SQL query correctly returns the desired result?

A.SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department WHERE total_salary > 500000
B.SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department WHERE SUM(salary) > 500000
C.SELECT department, SUM(salary) AS total_salary FROM employees GROUP BY department HAVING SUM(salary) > 500000
D.SELECT department, SUM(salary) AS total_salary FROM employees WHERE SUM(salary) > 500000 GROUP BY department
AnswerC

This query correctly groups rows by department, computes the total salary per group, and then applies HAVING to filter groups whose aggregate exceeds 500,000. In Spark SQL, HAVING is the proper clause for aggregate-based filtering, and it is evaluated after GROUP BY, so it works as required.

Why this answer

Filtering on an aggregate result requires the HAVING clause, which executes after GROUP BY. The query that groups by department, sums salary, and then applies HAVING with the aggregate condition returns only departments whose total salary exceeds 500,000, exactly matching the requirement.

Exam trap

The trap here is assuming that WHERE can filter aggregated results or that a SELECT alias can be used in WHERE, when in Spark SQL only HAVING can filter on aggregates after grouping.

12
MCQeasy

Which SQL function is used to create a temporary view that persists only for the duration of the current Spark session?

A.CREATE GLOBAL TABLE
B.CREATE TEMPORARY VIEW
C.CREATE PERSISTENT VIEW
D.CREATE SESSION TABLE
AnswerB

This command creates a temporary view that exists only within the current SparkSession. It is the ideal tool for ad-hoc analysis or intermediate transformations where the data does not need to be saved to long-term storage or shared across different clusters or users within the organization's wider data environment.

Why this answer

The CREATE TEMPORARY VIEW statement is the standard method for registering a DataFrame or table as a temporary view. These views are scoped to the SparkSession, making them invisible to other sessions or users. This is critical for modularizing complex SQL pipelines where intermediate results need to be referenced by name without polluting the global metastore or requiring permanent persistence in underlying storage.

Exam trap

Candidates often confuse 'TEMPORARY VIEW' with 'GLOBAL TEMPORARY VIEW'. They fail to realize that global views persist across sessions, whereas standard temporary views are strictly session-scoped and disappear upon termination.

13
MCQmedium

Which of the following is the most efficient way to convert a Spark DataFrame into a format suitable for low-latency SQL queries in Databricks?

A.Write the data as a collection of CSV files in the cloud storage.
B.Write the data into a Delta table.
C.Keep the data as a temporary view in the driver's memory.
D.Write the data as JSON files to exploit document-based query engines.
AnswerB

Delta tables are optimized for performance with features like Z-Ordering, data skipping, and statistics. By leveraging these features, Delta tables provide the best balance of write performance and low-latency read performance for SQL queries in Databricks, making them the preferred choice for analytical data storage in the lakehouse.

Why this answer

Delta Lake is the gold standard for Spark workloads because it brings ACID transactions, schema enforcement, and high performance to data lakes. Converting DataFrames to Delta tables enables indexing, data skipping, and file-level statistics, which are essential for low-latency SQL access. This approach replaces older formats like Parquet, offering superior capabilities and seamless integration with the Databricks engine, making it the standard practice for modern data lake architecture.

Exam trap

Candidates often suggest converting to Parquet or JSON, believing these are the standard for SQL. They overlook that Delta Lake is the native, optimized format for the Databricks Lakehouse architecture.

14
MCQeasy

A developer runs `spark.sql("SELECT * FROM sales")` and receives an error stating the table or view cannot be found, even though a Parquet directory exists at `dbfs:/mnt/raw/sales/`. The developer wants to query that Parquet data using Spark SQL without moving or copying the files. Which action should the developer take?

A.Create a table using `CREATE TABLE sales USING parquet LOCATION 'dbfs:/mnt/raw/sales/'` and then query it.
B.Set `spark.sql.warehouse.dir` to `dbfs:/mnt/raw/sales/` and rerun the query.
C.Execute `REFRESH TABLE sales` so Spark reloads the metadata from disk.
D.Run `MSCK REPAIR TABLE sales` to register the directory with the metastore.
AnswerA

Defining a table with `USING parquet` and a `LOCATION` clause registers the existing directory in the metastore so Spark SQL can resolve the name `sales`. Because the data stays in place, no copying occurs, and subsequent queries read the Parquet files directly. This matches the requirement to query existing files without relocation.

Why this answer

Spark SQL resolves table names through the metastore catalog, so a directory on storage is invisible until a table definition points at it. Using `CREATE TABLE ... USING parquet LOCATION ...` registers the path without moving data, enabling immediate querying by name.

Commands that repair or refresh metadata presuppose an existing table and cannot create one.

Exam trap

The trap here is confusing metadata-maintenance commands such as `MSCK REPAIR TABLE` or `REFRESH TABLE` with table creation, when those commands only operate on tables that already exist in the catalog.

15
Multi-Selectmedium

A developer is working with a Spark SQL DataFrame that contains a column 'tags' which is an array of strings. The developer needs to filter rows where the array contains the string 'spark' and also transform the array to uppercase. Which TWO Spark SQL functions should be used to achieve these requirements? (Choose two.)

Select 2 answers
A.upper(tags)
B.array_contains(tags, 'spark')
C.transform(tags, x -> upper(x))
D.filter(tags, x -> x = 'spark')
E.explode(tags)
AnswersB, C

The array_contains function checks if a given value exists in an array. It returns a boolean, which can be used in a filter condition. This directly addresses the requirement to filter rows where the array contains 'spark'. It is the standard function for this purpose in Spark SQL.

Why this answer

To filter rows where the array contains 'spark', array_contains is the direct and efficient function. To transform each element of the array to uppercase, transform with a lambda using upper is the correct approach. Together, they satisfy both requirements without altering the DataFrame's structure.

Exam trap

The trap here is confusing element-level filtering within an array (using filter) with row-level filtering based on array contents (using array_contains).

16
MCQhard

A developer is using Spark SQL to join two DataFrames: a large fact table 'orders' and a smaller dimension table 'customers'. The join key is customer_id. The developer notices that the join is causing a shuffle and wants to avoid it. Which Spark SQL technique should be used to eliminate the shuffle for this join?

A.Use a broadcast hint: SELECT /*+ BROADCAST(customers) */ * FROM orders JOIN customers ON orders.customer_id = customers.customer_id
B.Set spark.sql.autoBroadcastJoinThreshold to -1 to force broadcast joins.
C.Repartition both DataFrames on customer_id before joining.
D.Use a merge hint: SELECT /*+ MERGE(customers) */ * FROM orders JOIN customers ON orders.customer_id = customers.customer_id
AnswerA

The broadcast hint tells Spark to broadcast the smaller 'customers' table to all executors, avoiding a shuffle of the large 'orders' table. This is the correct technique when one side of the join is small enough to fit in memory. Spark SQL supports the BROADCAST hint, and it is the standard way to eliminate shuffle for such joins. The hint must be placed immediately after SELECT.

Why this answer

The broadcast hint instructs Spark to send the smaller table to all executors, so the large table can be joined locally without shuffling. This is the optimal approach when one side of the join is small enough to fit in memory. Other options either disable broadcast, use an invalid hint, or introduce additional shuffles.

The broadcast join is a key optimization in Spark SQL for star-schema joins.

Exam trap

The trap here is confusing the autoBroadcastJoinThreshold setting: setting it to -1 disables broadcast joins, while increasing it enables broadcasting for larger tables.

17
Multi-Selecthard

Which TWO of the following are true concerning Spark SQL's handling of NULL values?

Select 2 answers
A.The COUNT(column_name) function excludes NULL values from the count.
B.NULL values are treated as zero in all mathematical operations.
C.The COUNT(*) function includes rows where all columns contain NULL values.
D.The 'IS NULL' condition is not supported in Spark SQL; use '== NULL' instead.
E.Joining on columns that contain NULL values will always result in an inner join match.
AnswersA, C

In Spark SQL, aggregate functions that target a specific column, such as COUNT(col), ignore NULL values. This behavior is standard ANSI SQL and is vital to understand when calculating metrics like non-null record counts, as failing to account for this can lead to significant errors in business reporting.

Why this answer

Correctly managing NULLs is crucial for data accuracy. Spark SQL treats NULLs as unknown values. Aggregate functions like SUM and COUNT(col) skip NULLs, while count(*) includes them.

Understanding these nuances is essential for developers to write robust SQL queries that correctly interpret missing data, avoiding common pitfalls in reporting and data quality validation processes within Databricks production environments.

Exam trap

Test-takers frequently assume COUNT(*) and COUNT(column_name) treat NULL values identically, leading to incorrect calculations when missing data is present.

18
MCQmedium

A data engineer has two Spark SQL DataFrames: customers (customer_id, name) and orders (order_id, customer_id, amount). They want to retrieve every customer along with their orders, but they also want to include customers who have placed no orders, showing null for the order columns. Which operation should they use?

A.customers.join(orders, customers.customer_id == orders.customer_id, 'full')
B.customers.join(orders, customers.customer_id == orders.customer_id, 'inner')
C.customers.join(orders, customers.customer_id == orders.customer_id, 'left')
D.customers.join(orders, customers.customer_id == orders.customer_id, 'right')
AnswerC

A left outer join keeps all rows from the left DataFrame, customers, and matches rows from orders where possible. Customers with no orders appear with null values in the order columns, which is exactly the desired behavior. This satisfies the requirement to include every customer while optionally attaching their orders.

Why this answer

A left outer join preserves every row from the customers DataFrame while attaching matching order rows, so customers without orders appear with nulls in the order columns. Inner, right, and full outer joins either drop unmatched customers or add unmatched orders, so they do not meet the stated requirement.

Exam trap

The trap here is mixing up left and right outer joins by focusing on the table that has more rows rather than on which DataFrame must be fully preserved.

19
MCQeasy

A developer is writing a PySpark script that must run a SQL statement against DataFrames already registered as temporary views named orders and returns. The developer wants the query to use Spark SQL syntax while returning a DataFrame that can be further transformed with the DataFrame API. Which call accomplishes this?

A.spark.sql("SELECT o.order_id, r.amount FROM orders o JOIN returns r ON o.order_id = r.order_id")
B.spark.catalog.sql("SELECT o.order_id, r.amount FROM orders o JOIN returns r ON o.order_id = r.order_id")
C.spark.executeSql("SELECT o.order_id, r.amount FROM orders o JOIN returns r ON o.order_id = r.order_id")
D.spark.sqlContext.runSql("SELECT o.order_id, r.amount FROM orders o JOIN returns r ON o.order_id = r.order_id")
AnswerA

spark.sql executes a SQL string against the current catalog and returns a DataFrame, so the result can be chained with DataFrame transformations such as filter or withColumn. Because orders and returns are registered as temporary views, they resolve in the session catalog. This is the standard way to mix SQL and the DataFrame API in one pipeline.

Why this answer

SparkSession.sql runs a SQL string against views registered in the session catalog and returns a DataFrame, allowing the result to be combined with DataFrame transformations. Because orders and returns are temporary views in the same session, the query resolves and returns a join result that can be further processed. The other calls reference methods that do not exist on those objects.

Exam trap

The trap here is confusing the catalog interface, which manages metadata such as tables and functions, with the SQL execution entry point on the SparkSession.

20
MCQeasy

Which clause is used in a SELECT statement to filter the results based on aggregated values?

A.WHERE
B.HAVING
C.FILTER
D.LIMIT
AnswerB

The HAVING clause is designed specifically to filter data after the GROUP BY and aggregation operations have been performed. This is the only way to apply predicates to the results of aggregate functions, which is a required capability for generating summarized insights from large datasets in Spark SQL.

Why this answer

The HAVING clause is essential for filtering the output of an aggregation. While WHERE filters rows before aggregation, HAVING filters groups after the aggregation is calculated. Distinguishing between these two clauses is a foundational concept in SQL and critical for developers using Spark SQL to summarize data.

Failure to use the correct filter leads to syntax errors or incorrect analytical results, highlighting the necessity of this fundamental SQL skill.

Exam trap

Candidates commonly confuse WHERE and HAVING clauses, attempting to filter aggregate metrics inside the WHERE clause before aggregation occurs.

21
MCQmedium

A data engineer runs the following statement in a Databricks notebook: CREATE OR REPLACE TEMP VIEW high_value_customers AS SELECT customer_id, SUM(amount) AS total FROM sales GROUP BY customer_id HAVING SUM(amount) > 10000. Later, the same engineer opens a new notebook attached to the same cluster and tries to run SELECT * FROM high_value_customers. What will happen?

A.The query fails with an analysis error only if the underlying sales table was dropped; otherwise the temporary view remains globally accessible.
B.The query succeeds only if the second notebook calls REFRESH TABLE high_value_customers before selecting from it, because temp views are lazily registered.
C.The query fails with TABLE_OR_VIEW_NOT_FOUND because the temporary view is scoped to the SparkSession that created it and is not visible to a different notebook session.
D.The query succeeds because temporary views are stored in the cluster-wide Spark catalog and shared across all notebooks on that cluster.
AnswerC

Temporary views live in the session-scoped catalog of the SparkSession that created them. A second notebook attached to the same cluster receives a separate SparkSession, so the name high_value_customers cannot be resolved and Spark raises TABLE_OR_VIEW_NOT_FOUND. Persisting the result as a managed or external table would be required for cross-notebook visibility.

Why this answer

Temporary views are registered in a session-scoped catalog, so a view created in one notebook is invisible to other notebooks even when they run on the same cluster. A second notebook gets its own SparkSession and cannot resolve the view name, producing TABLE_OR_VIEW_NOT_FOUND. To share results across sessions, the engineer must persist them as a table in the metastore or use a global temporary view in the global_temp database.

Exam trap

The trap here is assuming that two notebooks attached to the same cluster share one SparkSession and therefore share temporary views, when in fact each notebook session has its own session-scoped catalog.

22
Multi-Selectmedium

A data engineer is writing a Spark SQL query that joins a `transactions` table to a `customers` table on `customer_id`. The engineer wants to ensure that rows from `transactions` with no matching customer are still returned, with nulls for customer columns, and also wants to exclude duplicate rows that arise from the join. Which TWO clauses should the engineer include? (Choose two.)

Select 2 answers
A.Use a `LEFT OUTER JOIN` between `transactions` and `customers`.
B.Apply `SELECT DISTINCT` to the final result set.
C.Use an `INNER JOIN` instead of an outer join.
D.Use a `FULL OUTER JOIN` between the two tables.
E.Add a `GROUP BY` on all columns from both tables.
AnswersA, B

A `LEFT OUTER JOIN` preserves every row from the left `transactions` table and fills unmatched customer columns with nulls. This satisfies the requirement to retain transactions lacking a matching customer. Inner joins would drop those rows, so the outer join is essential to the scenario's stated goal of not losing left-side records.

Why this answer

Preserving unmatched left-side rows requires an outer join oriented to the left table, and eliminating duplicated combinations requires a distinct projection. Together, a left outer join plus `SELECT DISTINCT` returns every transaction, matches customers where possible, and collapses repeated pairs into single rows. Inner and full outer joins change which unmatched rows survive and do not meet the stated retention rule.

Exam trap

The trap here is treating deduplication as something a join type provides, when duplicate elimination requires a separate distinct or aggregate operation after the join is performed.

23
MCQeasy

Which clause is used in a Spark SQL query to limit the number of rows returned by a query, and in which logical order is it executed?

A.LIMIT, executed after ORDER BY.
B.TAKE, executed before ORDER BY.
C.FETCH, executed before WHERE.
D.TOP, executed after GROUP BY.
AnswerA

In SQL, LIMIT is applied after the final result set has been determined, including any sorting required by the ORDER BY clause. This ensures that if you request the top 10 rows, you receive the 10 rows with the highest or lowest values as determined by the specified column ordering.

Why this answer

The LIMIT clause is a common SQL operation used to restrict result sets. In Spark SQL, it is essential to understand that it is applied after sorting if an ORDER BY is present, or simply on the result stream if not. Using LIMIT is a critical performance practice to avoid overwhelming the driver when previewing large datasets in a notebook environment.

Exam trap

Candidates often assume LIMIT is applied before sorting, which would result in non-deterministic data. They fail to realize the logical execution order is crucial for consistent results.

24
MCQmedium

You need to combine two datasets in Spark SQL, retaining all records from the left table and matching records from the right table, while filling unmatched right columns with null values. Which join type should you use?

A.RIGHT OUTER JOIN
B.FULL OUTER JOIN
C.LEFT OUTER JOIN
D.INNER JOIN
AnswerC

Preserving all rows from the primary left table and augmenting them with matching values from the right table defines the left outer join. Unmatched columns are automatically padded with null values, exactly meeting the business requirement.

Why this answer

A left outer join ensures every single record from the left dataset appears in the final result set, regardless of whether a matching key exists in the right dataset. Missing matches on the right side are populated with null values, maintaining structural integrity for downstream analysis.

Exam trap

Candidates frequently confuse LEFT OUTER JOIN with RIGHT OUTER JOIN or FULL OUTER JOIN, accidentally swapping the order of tables or including unwanted nulls from the left side.

25
Multi-Selecthard

You are using Spark SQL to join two large Delta tables, orders and customers, on a common column customer_id. The orders table is partitioned by order_date, and the customers table is not partitioned. You need to ensure the join is efficient and minimizes shuffling. Which TWO actions should you take? (Choose two.)

Select 2 answers
A.Enable adaptive query execution (AQE) and set spark.sql.adaptive.enabled to true.
B.Use the MERGE command to combine the tables.
C.Partition the customers table by customer_id to match the orders table.
D.Broadcast the customers table if it is small enough to fit in memory.
E.Repartition both tables by customer_id before the join.
AnswersA, D

AQE can dynamically optimize joins by converting sort-merge joins to broadcast joins if one side is small after initial stages, and by coalescing partitions. Enabling AQE helps minimize shuffling and improves performance. It is a best practice for large joins in Spark SQL, especially when statistics are outdated or data skew exists.

Why this answer

Broadcasting the smaller table eliminates shuffling of the larger table. Enabling AQE allows Spark to dynamically optimize the join, potentially converting to a broadcast join or adjusting partitions. These two actions together minimize shuffling and improve efficiency.

Exam trap

The trap here is assuming that repartitioning both tables is always beneficial, or that partitioning the smaller table by the join key will help, when in fact it can cause more shuffling or small file problems.

26
MCQeasy

In Spark SQL, what is the primary difference between a temporary view and a global temporary view?

A.Temporary views persist after the cluster is terminated, while global temporary views do not.
B.Temporary views are accessible only within the current session, while global temporary views are accessible across all sessions.
C.Temporary views are written to the Hive Metastore, while global temporary views are only in memory.
D.Global temporary views are faster to query because they are cached by default.
AnswerB

Temporary views are bound to the specific Spark session that created them, ensuring isolation. Global temporary views are bound to the Spark application and are accessible by any session on the same cluster, allowing shared access to temporary datasets across different notebooks or users running on the same cluster.

Why this answer

Understanding scope is critical for managing data access in multi-user Databricks environments. Temporary views are session-specific, ensuring data isolation between users. Global temporary views are visible to all sessions on the cluster and are stored in the 'global_temp' database.

This distinction is vital for maintaining security and avoiding namespace collisions when multiple data engineers are working simultaneously on the same shared cluster infrastructure.

Exam trap

Candidates often incorrectly believe global temporary views are persistent across cluster restarts or shared across different workspaces, rather than just being session-agnostic within the same cluster.

27
MCQmedium

You are processing a large dataset in Spark SQL and need to ensure that small files are avoided when writing data to Delta Lake. Which approach effectively minimizes small file generation during write operations?

A.Execute a DROP TABLE command before overwriting the existing table every time.
B.Increase the spark.sql.shuffle.partitions configuration to a very high value.
C.Enable 'autoOptimize' and 'optimizeWrite' at the Delta table level.
D.Use the 'repartition(1)' method on the DataFrame before writing to storage.
AnswerC

Enabling these properties allows Databricks to automatically coalesce small writes into larger files during the write operation itself. This significantly reduces the number of small files created by concurrent or frequent streaming writes, ensuring that data is laid out optimally for future analytical queries without manual intervention.

Why this answer

Optimizing file sizes is crucial for read performance and metadata management in Delta Lake. Using the OPTIMIZE command or enabling Auto Optimize are the standard patterns to address the small file problem. These techniques consolidate fragmented data into larger, performant files, reducing the overhead on the query engine and preventing performance degradation during subsequent read operations.

This is a fundamental skill for maintaining healthy, scalable data lakes on Databricks.

Exam trap

Candidates often suggest manual partitioning or repartitioning before every write. They fail to recognize that enabling built-in Delta Lake features like Auto Optimize is the more efficient, automated solution.

28
MCQmedium

An analyst notices that a Spark SQL query filtering a Delta table with `WHERE order_date = '2024-03-15'` scans far more data than expected, even though the table is partitioned by `order_date`. The partition column was loaded as a string in `yyyy-MM-dd` format. Which explanation best accounts for the excessive scan?

A.The literal is compared against a partition column of a different type or format, so pruning cannot match partitions.
B.Partition pruning is disabled by default and must be enabled with `spark.sql.optimizer.enablePartitionPruning`.
C.The query lacks a `LIMIT` clause, which forces Spark to read every file in the table.
D.Delta tables never support partition pruning; only Parquet tables do.
AnswerA

If the partition column is stored as a string and the literal is cast or formatted differently, Catalyst may fail to derive a static partition predicate and fall back to scanning all partitions. Type or format mismatches between the filter literal and the partition column defeat pruning. Aligning the literal's type and format with the column restores efficient partition elimination.

Why this answer

Partition pruning depends on Catalyst proving that a filter predicate matches partition values, which requires the literal's type and format to align with the partition column. A string partition column compared to a differently typed or formatted literal prevents static pruning, causing a full scan. Correcting the literal's type and format lets the optimizer eliminate irrelevant partitions.

Exam trap

The trap here is blaming a missing configuration flag for poor pruning, when pruning is automatic and fails only when the predicate and partition column types or formats are incompatible.

29
MCQmedium

When joining two large tables in Spark SQL, which join type helps avoid expensive shuffles by loading a small table into memory on all executor nodes?

A.Shuffle Hash Join
B.Broadcast Hash Join
C.Sort Merge Join
D.Cartesian Product Join
AnswerB

Broadcast Hash Join optimizes performance by broadcasting the smaller table to all executors. Because the small table is available locally on every node, the join operation avoids large data shuffles, making it significantly faster for scenarios where one table can comfortably fit within the driver-defined broadcast memory threshold.

Why this answer

A Broadcast Hash Join is a highly efficient join strategy in Spark SQL. By marking the smaller table as a broadcast candidate, Spark sends a complete copy of that table to every executor node. This allows the join to be performed locally at each node, eliminating the need to shuffle the large table across the network, which is often the primary bottleneck in large-scale distributed join operations.

Exam trap

Candidates often select Sort-Merge Join or Shuffle Hash Join when trying to avoid network shuffles, forgetting that only broadcasting eliminates network movement for the small table.

30
MCQmedium

What is the primary purpose of the 'Cache' command in Spark SQL?

A.To permanently store the data on the disk for future use.
B.To keep the data in memory to avoid redundant re-computation.
C.To force the garbage collector to free up memory immediately.
D.To automatically partition the data across the cluster for faster access.
AnswerB

The primary goal of caching is to keep a computed DataFrame in memory so that subsequent actions triggered on that data do not need to re-execute the entire lineage of transformations. This is crucial for performance when the same data is used multiple times within a job.

Why this answer

Caching allows developers to persist frequently accessed data in memory across multiple actions. By avoiding repeated reads from storage and re-computation of transformations, caching significantly speeds up iterative workloads, such as machine learning training or complex dashboard refreshes. However, it must be used judiciously, as memory is a finite resource, and unnecessary caching can lead to OOM errors and overall performance degradation.

Exam trap

Examinees often confuse caching with permanent storage or assume it automatically speeds up every single-use query without needing an iterative context.

31
MCQmedium

A developer is building a Spark SQL pipeline in a Databricks notebook. They need to persist an intermediate DataFrame, built from a transformation of a Delta table, as a physical table in the current database so other notebooks in the same cluster can query it. They also want the table metadata to be managed by the metastore and the data to reside in the default warehouse directory. Which Spark SQL statement should they use?

A.CREATE OR REPLACE TABLE intermediate_sales AS SELECT * FROM sales WHERE region = 'EU'
B.CREATE OR REPLACE GLOBAL TEMP VIEW intermediate_sales AS SELECT * FROM sales WHERE region = 'EU'
C.CREATE OR REPLACE VIEW intermediate_sales AS SELECT * FROM sales WHERE region = 'EU'
D.CREATE OR REPLACE TEMP VIEW intermediate_sales AS SELECT * FROM sales WHERE region = 'EU'
AnswerA

This statement creates a managed Delta table in the current database, stores its data in the warehouse directory, and registers metadata in the metastore. Because it is a managed table, it persists beyond the session and is queryable from other notebooks on the same cluster, satisfying both the persistence and metastore-management requirements described in the scenario.

Why this answer

Creating an OR REPLACE TABLE with a SELECT statement materializes the transformed data as a managed Delta table, registers it in the metastore, and stores it in the default warehouse location. This matches the need for a persistent, cross-session-accessible physical table, unlike temporary views, global temporary views, or logical views, which do not persist materialized data.

Exam trap

The trap here is assuming that a global temporary view persists data across sessions or is stored in the metastore, when it is still session-scoped and stores no physical data.

32
Multi-Selectmedium

A developer writes a Spark SQL query that groups orders by region and computes the total revenue per region, but also needs to return the number of distinct customers per region in the same result set. Which TWO expressions correctly compute the distinct customer count per region in a single GROUP BY region query? (Choose two.)

Select 2 answers
A.COUNT(customer_id) FILTER (WHERE customer_id IS NOT NULL)
B.COUNT(DISTINCT customer_id)
C.SUM(DISTINCT customer_id)
D.COLLECT_SET(customer_id)
E.APPROX_COUNT_DISTINCT(customer_id)
AnswersB, E

COUNT(DISTINCT customer_id) is a native aggregate that counts unique non-null customer_id values within each region group. Spark SQL supports this directly inside a GROUP BY region query, so it returns the distinct customer count per region without a subquery. It handles nulls by ignoring them, which matches typical distinct-count semantics in SQL.

Why this answer

To return a distinct customer count per region within a single GROUP BY region query, the developer can use COUNT(DISTINCT customer_id), which gives an exact deduplicated count per group, or APPROX_COUNT_DISTINCT(customer_id), which returns an approximate count using a sketch and is preferable when cardinality is high. Both are valid aggregates that operate per group and produce one value per region.

Exam trap

The trap here is treating COUNT with a FILTER clause as equivalent to a distinct count, when filtering nulls does not remove duplicate customer_id values within a region.

33
MCQeasy

An analyst has a Spark SQL DataFrame named events with a string column event_time in the format 'yyyy-MM-dd HH:mm:ss'. They want to add a new column event_date containing only the date portion, keeping the original column intact. Which expression should they use in a select statement?

A.date_format(event_time, 'yyyy-MM-dd')
B.trunc(event_time, 'MM')
C.substring(event_time, 1, 10)
D.to_date(event_time, 'yyyy-MM-dd HH:mm:ss')
AnswerD

The to_date function parses the string using the supplied pattern and returns a date value containing only the date portion. Using the format string ensures correct parsing of the timestamp text. This produces the desired event_date column while leaving the original event_time column unchanged, which is exactly what the scenario requires.

Why this answer

Using to_date with the matching pattern correctly parses the timestamp string and returns a date-typed column containing only the date component. The other functions either return strings, operate on date types rather than strings, or rely on fragile character extraction, so they do not produce a proper date column as required.

Exam trap

The trap here is choosing substring because it visually looks like it extracts the date, while ignoring that it returns a string and is not robust to format variations.

34
MCQhard

A developer needs to add a computed column `discounted_price` equal to `price * 0.9` to an existing Delta table `products` and persist the change so all future queries see the new column. The table already contains data. Which statement should the developer run?

A.`ALTER TABLE products ADD COLUMNS (discounted_price DOUBLE)`
B.`UPDATE products SET discounted_price = price * 0.9`
C.`ALTER TABLE products ADD COLUMNS (discounted_price DOUBLE GENERATED ALWAYS AS (price * 0.9))`
D.`CREATE OR REPLACE TABLE products AS SELECT *, price * 0.9 AS discounted_price FROM products`
AnswerC

A generated column defined with `GENERATED ALWAYS AS` is computed automatically from the expression whenever rows are written, and adding it to a Delta table backfills values for existing rows. This persists the derived value in the table so all future queries see `discounted_price` populated. It is the declarative way to express the computed column in Spark SQL on Delta.

Why this answer

Adding a persisted computed column to a Delta table is done with `ALTER TABLE ... ADD COLUMNS` using a `GENERATED ALWAYS AS` expression. Spark computes the value from the base column for existing and future rows, so queries see a populated `discounted_price` without a manual update.

Statements that assume the column already exists or recreate the table either fail or risk data integrity.

Exam trap

The trap here is assuming that adding a plain column automatically populates it from an expression, when a bare `ADD COLUMNS` leaves existing rows null and requires a generated-column clause to derive values.

35
MCQmedium

Which of the following Spark SQL configuration settings should be adjusted to prevent the 'Driver OOM' error when collecting massive amounts of query results to the driver node?

A.spark.driver.maxResultSize
B.spark.executor.memory
C.spark.sql.shuffle.partitions
D.spark.memory.fraction
AnswerA

This configuration sets the limit on the total size of serialized results of all actions that can be returned to the driver. By increasing this value, you allow larger result sets, though it is often safer to rewrite the query to write the results to storage rather than collecting them locally.

Why this answer

Collecting data to the driver node is a dangerous operation in distributed computing because the driver has limited heap memory. Spark provides configuration limits to prevent users from accidentally crashing the driver by pulling too much data from the executors. Adjusting these settings—or better, avoiding collecting altogether—is a key skill for Databricks developers to maintain cluster stability in production environments.

Exam trap

Candidates often confuse 'spark.driver.maxResultSize' with cluster-level memory configurations like 'spark.executor.memory'. They incorrectly try to increase executor memory to solve a driver-side data collection crash.

36
MCQeasy

A data analyst needs to run a Spark SQL query that returns the top 5 highest-paid employees from a table named employees, ordered by salary descending. Which query correctly returns exactly five rows?

A.SELECT TOP 5 * FROM employees ORDER BY salary DESC
B.SELECT * FROM employees ORDER BY salary DESC LIMIT 5
C.SELECT * FROM employees ORDER BY salary DESC FETCH FIRST 5 ROWS ONLY
D.SELECT * FROM employees LIMIT 5 ORDER BY salary DESC
AnswerB

This query sorts all employees by salary in descending order and then limits the result to the first five rows. In Spark SQL, LIMIT after ORDER BY returns the top N rows according to the sort, which exactly matches the requirement to get the five highest-paid employees.

Why this answer

To get the top 5 highest-paid employees, the query must sort by salary descending and then apply LIMIT 5. Spark SQL supports ORDER BY followed by LIMIT, which returns the first five rows after sorting, exactly matching the requirement.

Exam trap

The trap here is assuming that other SQL dialects' TOP or FETCH FIRST syntax works in Spark SQL, or that LIMIT can precede ORDER BY.

37
MCQeasy

Which SQL function is used to concatenate strings while allowing you to specify a custom separator, handling null values by ignoring them?

A.concat()
B.concat_ws()
C.array_join()
D.format_string()
AnswerB

The 'concat_ws' function accepts a separator as its first argument and handles NULL values by ignoring them. This behavior is crucial for data cleaning and string formatting tasks where missing values should not invalidate the entire concatenated output, ensuring a consistent and readable result string for downstream consumers.

Why this answer

The 'concat_ws' function stands for 'concatenate with separator'. It is specifically designed to take a delimiter as the first argument, followed by a variable number of strings. A key feature of 'concat_ws' is its ability to skip NULL values automatically, preventing the entire result from becoming NULL—a common issue with the standard 'concat' function.

This makes it ideal for building CSV-like strings or concatenating fields that may contain missing data.

Exam trap

Many candidates confuse concat_ws() with standard concat(), overlooking how standard concat turns the entire output null if any single column contains a null value.

38
MCQhard

When executing a Spark SQL query, what does the Catalyst optimizer perform during the 'Analysis' phase?

A.It translates the logical plan into a series of physical execution steps.
B.It checks the existence of tables and columns in the catalog.
C.It pushes down predicates to the data source to minimize I/O.
D.It chooses the most efficient join strategy based on table size.
AnswerB

The Analysis phase is explicitly responsible for verifying that all referenced objects, such as tables and columns, exist in the underlying metadata catalog. It resolves these names into concrete references, which is a prerequisite for all further optimization and execution steps in the Spark SQL pipeline.

Why this answer

The Analysis phase is the first step in the query optimization process where Spark resolves identifiers and validates the schema. It checks if tables and columns exist in the catalog and resolves data types. Without this step, Spark would not be able to build a logical plan for the query, as it would not know which data to fetch or how to process the specified columns and tables correctly.

Exam trap

Candidates often confuse the Analysis phase with physical optimization or logical plan generation, forgetting that checking catalog existence happens first.

39
MCQhard

A developer has a Delta table events with a high-cardinality column user_id and a low-cardinality column country. A query filters on country = 'US' and also on user_id IN (...). The developer runs EXPLAIN and sees a full scan of all files. Which statement about data skipping and the Delta table's statistics correctly explains why the filter on country is not skipping files?

A.Delta data skipping only works on columns used in JOIN conditions, so a WHERE filter on country is never eligible for file pruning regardless of statistics.
B.Data skipping requires the filtered column to be the first column in the table's partitioning scheme, so country must be a partition column for any file pruning to occur.
C.Data skipping is disabled by default and must be enabled with spark.databricks.delta.dataSkipping.enabled before any file pruning can happen on any column.
D.Delta data skipping uses per-file min/max statistics, and if the table was written without collecting statistics or the file count is small, the country filter cannot eliminate files even though the value is low cardinality.
AnswerD

Delta data skipping relies on per-file statistics such as min/max and null counts stored in the transaction log. If statistics were not collected, or if there are too few files for skipping to matter, the optimizer cannot prune files for country = 'US'. Low cardinality alone does not guarantee skipping; the statistics must exist and the file layout must be granular enough to separate values.

Why this answer

Delta data skipping prunes files using per-file statistics such as min/max and null counts recorded in the transaction log. A filter on country can only eliminate files if those statistics were collected at write time and the file layout separates country values. Low cardinality does not by itself enable skipping, and skipping is not limited to join conditions or partition columns, nor does it require a special enablement flag for basic operation.

Exam trap

The trap here is assuming that a low-cardinality filter column automatically triggers file skipping, when skipping actually depends on the presence and usefulness of per-file statistics in the transaction log.

40
Multi-Selecthard

Which THREE of the following are valid ways to monitor or debug Spark SQL query performance in Databricks?

Select 3 answers
A.Use the 'EXPLAIN' statement to inspect the physical plan of the query.
B.Examine the Spark UI to review stage-level details and task metrics.
C.Manually restart the cluster every time a query takes more than 10 seconds.
D.Use the Databricks Query Profile to visualize the query execution tree.
E.Increase the driver memory to the maximum available for all jobs.
AnswersA, B, D

The EXPLAIN command is essential for viewing the logical and physical plans generated by the Catalyst optimizer. It reveals how Spark intends to execute the query, showing joins, filtering, and scans, which helps developers identify if the plan is optimized or if performance is hindered by inefficient operations.

Why this answer

Monitoring tools like the Spark UI, Query Profile, and Explain plans are critical for developers to understand how their SQL code executes. They provide visibility into shuffle sizes, stage durations, and physical plan generation. Effectively using these tools is the difference between writing performant code and creating bottlenecks.

They allow developers to identify skewed data, suboptimal joins, and unnecessary data scanning, which are common issues in large-scale Spark SQL workloads.

Exam trap

Candidates often incorrectly include 'DESCRIBE HISTORY' as a performance debugging tool. While useful for auditing, it is not a primary tool for analyzing query execution plans or stage-level bottlenecks.

41
Multi-Selecthard

Which THREE of the following are valid ways to create a DataFrame from an existing table in Spark SQL?

Select 3 answers
A.spark.table('table_name')
B.spark.sql('SELECT * FROM table_name')
C.spark.read.table('table_name')
D.spark.open('table_name')
E.spark.from_table('table_name')
AnswersA, B, C

The 'spark.table()' method is a direct and efficient way to create a DataFrame by looking up the table name in the catalog. It is highly readable and is the standard way to retrieve a persistent table as a DataFrame for further transformation using the Spark API.

Why this answer

Spark provides multiple entry points to access table data. You can use the 'spark.table()' method for direct catalog access, 'spark.sql()' to execute a SELECT statement, or the 'spark.read.table()' method. All three provide the same underlying Dataset/DataFrame API, allowing for flexible programmatic interaction with metadata managed by the Hive Metastore or Unity Catalog, ensuring consistency across different development styles and API usage patterns in Databricks.

Exam trap

Candidates often select invalid or overly verbose DataFrame creation syntaxes, such as attempting to use non-existent SparkSession methods or confusing RDD loading commands with native table readers.

42
MCQmedium

Which of the following describes the behavior of a 'Broadcast Hash Join' in Spark SQL?

A.The larger table is shuffled to match the smaller table's partitions.
B.The smaller table is sent to all executors, avoiding a shuffle of the large table.
C.Both tables are shuffled to a common partition based on the join key.
D.The join is performed entirely on the driver node.
AnswerB

By broadcasting the smaller table, Spark eliminates the need to move the large dataset across the network. The large table's partitions are processed in parallel on each executor against a full local copy of the small table. This is the most efficient join type for small-to-large table operations.

Why this answer

A Broadcast Hash Join is a highly efficient join strategy where the smaller table is sent to all worker nodes, allowing the join to occur locally in memory. This eliminates data shuffles, which are usually the slowest part of a distributed join. Understanding when the optimizer chooses this—and when to force it—is essential for optimizing SQL performance in Databricks environments where network bandwidth is a common bottleneck.

Exam trap

Students often assume both tables are broadcast or that a broadcast join requires shuffling both datasets, overlooking the core design of sending only the small table.

43
MCQeasy

What is the result of applying the COALESCE function in Spark SQL when multiple arguments are provided?

A.It returns the sum of all arguments.
B.It returns the first non-null argument.
C.It returns the last non-null argument.
D.It throws an error if any argument is null.
AnswerB

COALESCE iterates through its arguments in order and returns the first one that is not null. If all arguments are null, it returns null. This is the idiomatic way in Spark SQL to perform null-replacement or provide fallback values for columns containing missing or null data in source systems.

Why this answer

The COALESCE function is a standard SQL tool for handling null values. It returns the first non-null argument from a list. This is extremely useful in data engineering for providing default values or merging columns that have sparse data.

Understanding how to use it helps in writing cleaner SQL that handles missing values without needing complex CASE WHEN statements, which improves code readability and maintainability.

Exam trap

Candidates often confuse COALESCE with ISNULL or NVL, mistakenly believing it returns the first null value encountered or performs a conditional check rather than returning the first non-null argument found.

44
MCQmedium

When working with Delta Lake tables in Databricks, which command should you use to optimize the physical layout of files to improve query performance?

A.COMPACT TABLE table_name
B.OPTIMIZE table_name
C.REORGANIZE TABLE table_name
D.VACUUM table_name
AnswerB

The OPTIMIZE command is the standard Delta Lake operation used to coalesce small files into larger, more performant files. It is an essential maintenance task for Databricks environments to ensure that storage layouts remain optimized for analytical queries, which significantly reduces the time spent on I/O operations.

Why this answer

Delta Lake provides the `OPTIMIZE` command to compact small files into larger ones, which is vital for maintaining performance as data grows. Frequent small writes can lead to file proliferation, degrading read speeds. Running `OPTIMIZE` regularly helps maintain efficient file sizes, enabling faster query execution by reducing metadata overhead and maximizing the benefits of data skipping through better file-level statistics.

Exam trap

Candidates often select 'VACUUM' or 'COMPACT' instead of 'OPTIMIZE'. They confuse the command for removing old files (VACUUM) with the command for improving query performance by compacting small files.

45
MCQmedium

A data engineer is working with a Spark SQL DataFrame in Databricks that has a column named event_time stored as a string in the format 'yyyy-MM-dd HH:mm:ss'. They need to filter rows where event_time falls within the last 7 days relative to the current timestamp. Which Spark SQL expression correctly achieves this?

A.SELECT * FROM events WHERE date_format(event_time, 'yyyy-MM-dd') >= date_sub(current_date(), 7)
B.SELECT * FROM events WHERE to_timestamp(event_time, 'yyyy-MM-dd HH:mm:ss') >= current_timestamp() - INTERVAL 7 DAYS
C.SELECT * FROM events WHERE event_time >= current_date() - 7
D.SELECT * FROM events WHERE unix_timestamp(event_time) >= unix_timestamp(current_timestamp()) - 604800
AnswerB

This expression uses to_timestamp with the correct format pattern to convert the string column into a timestamp, then compares it against current_timestamp() minus a 7-day interval. Spark SQL supports INTERVAL 7 DAYS syntax, and this correctly filters rows within the last week. It is the only option that both parses the string format correctly and uses a valid interval expression.

Why this answer

The correct expression uses to_timestamp to parse the string column with the explicit format, then compares it to current_timestamp() minus an interval of 7 days. This ensures accurate filtering based on the full timestamp, including time-of-day, and leverages Spark SQL's built-in interval arithmetic. Other options either ignore the time component, rely on implicit casting that may fail, or use less precise date-only comparisons.

Exam trap

The trap here is assuming that subtracting an integer from a date or timestamp will work as expected, when Spark SQL requires explicit interval syntax for timestamp arithmetic.

46
MCQeasy

Which of the following describes the behavior of a 'Left Outer Join' in Spark SQL?

A.It returns only rows that have matches in both the left and right tables.
B.It returns all rows from the left table and matched rows from the right table.
C.It returns all rows from the right table and matched rows from the left table.
D.It excludes all rows from both tables that do not have a matching key.
AnswerB

The definition of a Left Outer Join is that it preserves the entire left side of the join. For rows that do not have a corresponding key in the right table, Spark fills the right-side columns with NULLs, allowing the developer to see the full list from the left dataset.

Why this answer

A Left Outer Join is fundamental in SQL for merging datasets where you want to keep all records from the left table, regardless of whether a match exists in the right table. Understanding this ensures that data integration processes correctly handle non-matching records, preventing data loss during joins. It is a critical concept for analysts and developers building reports that require comprehensive views of primary entities with optional supplemental info.

Exam trap

Candidates often confuse Left Outer Joins with Full Outer Joins, mistakenly thinking the result set includes non-matching rows from BOTH tables rather than just the left table.

47
MCQmedium

A developer has a Spark SQL DataFrame `df` with an array column named `scores` containing integers. They need to create a new column `passing` that is true only when every element in `scores` is greater than or equal to 70. Which Spark SQL higher-order function should they use?

A.exists(scores, s -> s >= 70)
B.filter(scores, s -> s >= 70)
C.forall(scores, s -> s >= 70)
D.transform(scores, s -> s >= 70)
AnswerC

The forall higher-order function returns true only if the lambda predicate evaluates to true for every element in the array. In this scenario, forall(scores, s -> s >= 70) yields a single boolean column that is true exactly when all scores are at least 70, which matches the requirement. It short-circuits on the first false, making it efficient.

Why this answer

The forall higher-order function is designed to test whether every element in an array satisfies a given predicate, returning a single boolean. In this scenario, it correctly produces a column that is true only when all scores are 70 or higher. transform maps each element, filter selects elements, and exists checks for at least one match, none of which yield the required all-elements condition.

Exam trap

The trap here is confusing higher-order functions that return arrays (transform, filter) with those that return booleans (exists, forall), and mixing up exists (any) with forall (all).

48
MCQmedium

A data scientist is using Spark SQL to compute a running total of sales amounts for each customer, ordered by transaction date. The query must return, for each row, the sum of all previous sales for that customer up to and including the current row. Which window specification should be used?

A.OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
B.OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
C.OVER (PARTITION BY customer_id ORDER BY transaction_date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
D.OVER (PARTITION BY customer_id ORDER BY transaction_date RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
AnswerB

This window specification partitions by customer_id, orders by transaction_date, and defines the frame from the start of the partition up to the current row. SUM(sales_amount) over this window yields a running total per customer. The ROWS frame is explicit and ensures each row includes all preceding rows, which is exactly the requirement. It is the standard approach for cumulative sums.

Why this answer

A running total requires a window frame that starts at the beginning of the partition and ends at the current row. The specification with ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, combined with PARTITION BY customer_id and ORDER BY transaction_date, achieves this by summing all rows up to and including the current one for each customer. Other frames either sum future rows, include tied rows, or limit to a small window, none of which produce the desired cumulative sum.

Exam trap

The trap here is confusing ROWS with RANGE, or using a frame that sums future rows instead of preceding ones, which yields incorrect cumulative totals when duplicate dates exist.

49
MCQeasy

Which command is used to display the logical and physical execution plans for a given Spark SQL query?

A.SHOW PLAN
B.DESCRIBE QUERY
C.EXPLAIN SELECT * FROM table
D.DEBUG SELECT * FROM table
AnswerC

The 'EXPLAIN' command is the standard way to inspect Spark's query execution plans. It helps developers understand how the Catalyst optimizer parses and plans the query, allowing them to identify bottlenecks, such as unnecessary shuffles or full table scans, before executing the actual data-intensive operations on the large dataset.

Why this answer

The 'EXPLAIN' command is the essential tool for inspecting the Catalyst query optimizer's work. It provides a breakdown of the logical plan (the raw representation of the query), the analyzed plan, the optimized plan, and the physical plan (how Spark will actually execute the tasks). Understanding this output is crucial for performance tuning, as it reveals how Spark handles joins, filters, and projections before the query actually runs on the distributed cluster nodes.

Exam trap

Test-takers frequently confuse the EXPLAIN command with DESCRIBE or SHOW commands, failing to realize that EXPLAIN specifically outputs the Catalyst optimizer's execution plans.

50
MCQmedium

Which TWO of the following are benefits of using Delta Lake over standard Parquet files in Spark SQL?

A.Support for ACID transactions.
B.Ability to perform schema evolution and enforcement.
C.Faster raw I/O performance for single-column reads.
D.Automatic conversion of CSV files to optimized Parquet.
E.Compatibility with legacy Hive Metastore versions without modification.
AnswerA, B

ACID transactions ensure data integrity by allowing multiple concurrent readers and writers to interact with the data without corruption. This is a critical feature for data pipelines where consistency is paramount, and standard Parquet files do not provide this level of transactional guarantee by default.

Why this answer

Delta Lake extends the capabilities of standard Parquet by adding a transaction log and metadata layer. This enables ACID transactions, Time Travel, and schema enforcement, which are critical for robust data engineering. For a Databricks certified developer, knowing why Delta is the preferred format for the Lakehouse architecture is essential for building scalable, reliable, and maintainable data systems that surpass the limitations of raw file-based storage.

Exam trap

Candidates often mistakenly select performance-related features like 'automatic indexing' or 'auto-scaling' as benefits of Delta Lake, confusing general cloud platform capabilities with the specific ACID and schema features provided by the Delta format.

51
Multi-Selectmedium

A developer is using Spark SQL to analyze a DataFrame that contains a column named tags, which holds an array of strings for each row. The developer needs to filter rows where the array contains the string 'urgent' and also produce a new column with the number of elements in the array. Which TWO Spark SQL expressions should be used in the query? (Choose two.)

Select 2 answers
A.ARRAY_MAX(tags)
B.ARRAY_CONTAINS(tags, 'urgent')
C.EXPLODE(tags)
D.COLLECT_LIST(tags)
E.SIZE(tags)
AnswersB, E

ARRAY_CONTAINS is the correct function to test whether an array column includes a specific value. It returns a boolean and works directly on array-typed columns in Spark SQL. In a WHERE clause, it filters rows where the tags array contains 'urgent'. This is the idiomatic and efficient way to perform membership tests on arrays without exploding them first, preserving row granularity.

Why this answer

ARRAY_CONTAINS provides a direct boolean test for whether an array includes a given value, making it ideal for filtering rows without altering their structure. SIZE returns the element count of an array, which satisfies the need for a new column with the number of tags. Together, they allow the query to filter and augment the DataFrame efficiently.

Other functions like EXPLODE change row cardinality, COLLECT_LIST aggregates, and ARRAY_MAX finds a maximum, none of which meet the specific goals.

Exam trap

The trap here is confusing array inspection functions with generator or aggregate functions, leading to incorrect row-level results or unnecessary query complexity.

52
MCQmedium

A data engineer is building a Spark SQL pipeline that must return the top 3 highest-paid employees within each department from a Delta table named `employees` with columns `dept`, `name`, and `salary`. The engineer wants a single query that produces one row per qualifying employee, ranked by salary descending within each department, without collapsing rows. Which approach should be used?

A.Use `GROUP BY dept` with the `MAX(salary)` aggregate and a `HAVING` clause limiting results to three rows.
B.Use `ORDER BY salary DESC` on the full table and apply `LIMIT 3`.
C.Use the `rank()` window function partitioned by `dept` and ordered by `salary DESC`, then filter on the rank column.
D.Use `DISTINCT` on `dept` and `salary`, then sort the result with `SORT BY salary DESC`.
AnswerC

A window function with `PARTITION BY dept ORDER BY salary DESC` assigns a rank within each department without collapsing rows, and filtering on the rank column keeps only the top three per department. This is the idiomatic Spark SQL pattern for top-N-per-group and is fully supported in Databricks SQL warehouses and clusters.

Why this answer

Window functions are the correct tool for top-N-per-group problems because they compute a value across a set of rows related to the current row while preserving all rows. Partitioning by department and ordering by salary descending yields a per-department rank, and filtering that rank to three returns exactly the desired rows in a single query.

Exam trap

The trap here is assuming that a global `ORDER BY ... LIMIT` or a `GROUP BY` aggregate can satisfy a per-group top-N requirement, when only a window function preserves row granularity while ranking within partitions.

Ready to test yourself?

Try a timed practice session using only Using Spark SQL questions.