All Databricks exams

Free Databricks Certified Associate Developer for Apache Spark practice test: 30 questions with answers

30 original questions for Databricks Certified Associate Developer for Apache Spark, drawn from every topic area. Answer each one to see whether you got it right and why. No sign-up.

Free questions
30
Full bank
112 questions

Databricks Certified Associate Developer for Apache Spark exam guide: topics, cost and format

All 30 Databricks Certified Associate Developer for Apache Spark questions with answers

The same questions as the test above, grouped by exam topic. Open any question to see the answer and explanation.

DataFrame and Dataset API (4 questions)

  1. Question 1

    Which code correctly creates a SparkSession for a PySpark application?

    1. Aspark = SparkSession.create(appName='demo').start()
    2. Bspark = SparkSession.builder.appName('demo').getOrCreate()
    3. Cspark = new SparkSession.builder().appName('demo')
    4. Dspark = SparkContext.getSession().withName('demo').build()
    Show answer and explanation
    Correct answer: B

    SparkSession.builder configures the session and getOrCreate returns an existing session or creates one, which is the standard entry point. The other options use methods that do not exist on SparkSession or are not valid Python.

  2. Question 2

    A DataFrame df has columns name (string) and amount (double). Which expression adds a column tax that is 10 percent of amount?

    1. Adf.select('tax', df.amount * 0.1)
    2. Bdf.addColumn('tax', df.amount * 0.1)
    3. Cdf.withColumns('amount * 0.1' as 'tax')
    4. Ddf.withColumn('tax', df.amount * 0.1)
    Show answer and explanation
    Correct answer: D

    withColumn adds or replaces a column computed from an expression and returns a new DataFrame. The select form drops the other columns, while addColumn and the withColumns syntax are not valid DataFrame calls.

  3. Question 3

    Which code keeps only rows where the status column equals 'active' and the amount column is greater than 100?

    1. Adf.filter((col('status') == 'active') & (col('amount') > 100))
    2. Bdf.where(col('status') == 'active' and col('amount') > 100)
    3. Cdf.select(col('status') == 'active', col('amount') > 100)
    4. Ddf.filter(col('status') = 'active' & col('amount') > 100)
    Show answer and explanation
    Correct answer: A

    In PySpark column expressions, conditions are combined with & and each condition is wrapped in parentheses. Python's and does not work on Column objects, select returns boolean columns rather than filtering rows, and single equals is an assignment.

  4. Question 4

    Which method prints the schema of a DataFrame as a tree of column names, types, and nullability?

    1. Adf.count(), which returns the number of rows in the DataFrame as an integer value
    2. Bdf.describe(), which computes summary statistics such as count, mean, and standard deviation for numeric columns
    3. Cdf.head(0), which returns the first zero rows of the DataFrame as a list of Row objects
    4. Ddf.printSchema(), which prints the column names, data types, and nullability as a tree
    Show answer and explanation
    Correct answer: D

    printSchema prints the schema as a tree with names, types and nullability. Count returns a row count, describe computes statistics, and head(0) returns no rows.

Spark architecture and execution (4 questions)

  1. Question 5

    A PySpark job reads a large Parquet dataset and calls collect() on the result. The driver runs out of memory. What is the best change?

    1. ACall cache() before collect(), so that the data is stored in executor memory and passed to the driver more efficiently
    2. BIncrease the driver memory and keep collect(), since the driver must always hold the full result set in memory
    3. CReplace collect() with write() or show(n) so that results are written out or limited instead of being pulled to the driver
    4. DRepartition the DataFrame to a single partition before collect(), so that one executor sends the full result to the driver
    Show answer and explanation
    Correct answer: C

    collect() brings every row to the driver, so large results exhaust its memory no matter how much is added. Writing the output to storage or limiting it with show(n) keeps the data on executors, while caching or repartitioning do not reduce what collect() pulls to the driver.

  2. Question 6

    Which statement correctly describes lazy evaluation in Spark DataFrames?

    1. ATransformations such as filter and select are executed immediately, and each one materializes its full result before the next
    2. BTransformations build a logical plan and run only when an action such as count or write is called on the DataFrame
    3. CSpark executes every transformation on the driver first, and then sends the finished result to the executors
    4. DActions are deferred until the cluster is idle, so that the scheduler can batch them together automatically
    Show answer and explanation
    Correct answer: B

    Spark records transformations in a logical plan and executes them only when an action requires a result, which lets the optimizer improve the whole plan. Eager execution, cluster-idle scheduling and driver-first execution all contradict how Spark evaluates DataFrames.

  3. Question 7

    In the Spark architecture, which component coordinates the job, builds the DAG, and schedules tasks on the executors?

    1. AEach executor, which independently decides which stage to run next based on the data it holds locally
    2. BThe driver program, which runs the SparkSession, creates the logical and physical plans, and schedules tasks
    3. CThe cluster manager, which allocates the CPU and memory resources to the Spark application on each node
    4. DThe HDFS NameNode, which tracks the blocks of input data and tells each executor which splits to read
    Show answer and explanation
    Correct answer: B

    The driver hosts the SparkSession, converts the query into a DAG of stages and tasks, and schedules work on executors. The cluster manager allocates resources, executors run tasks, and the NameNode is a storage component rather than a Spark scheduler.

  4. Question 8

    A shuffle occurs in a Spark job. Which operation is the most likely cause?

    1. AA wide transformation such as groupBy or join, which requires rows with the same key to be moved to the same partition
    2. BA narrow transformation such as map or filter, which processes each partition without moving data between them
    3. CA read from a single Parquet file, which is loaded entirely into the memory of one executor at the start
    4. DA select that keeps only three columns from a DataFrame that already lives on each executor locally
    Show answer and explanation
    Correct answer: A

    Wide transformations such as groupBy and joins need data with the same key to be co-located, which triggers a shuffle across the network. Narrow transformations and column selections process each partition independently, so they do not shuffle.

Data sources and I/O (4 questions)

  1. Question 9

    Which code reads a CSV file with a header row and lets Spark infer the column types?

    1. Aspark.read.format('text').load('/data/sales.csv', header=True)
    2. Bspark.load.csv('/data/sales.csv', header=True, schema=True)
    3. Cspark.read.csv('/data/sales.csv', header=True, inferSchema=True)
    4. Dspark.read.json('/data/sales.csv', header=True, inferSchema=True)
    Show answer and explanation
    Correct answer: C

    spark.read.csv with header=True and inferSchema=True reads the header and infers types from the data. The text format does not parse columns, load.csv is not a reader method, and the json reader cannot parse CSV.

  2. Question 10

    Which write mode replaces the data at the output path with the new DataFrame's rows when writing Parquet?

    1. Adf.write.mode('ignore').parquet(path), which does nothing if the path already exists and leaves its data unchanged
    2. Bdf.write.mode('append').parquet(path), which adds the new rows to the files that already exist there
    3. Cdf.write.mode('overwrite').parquet(path), which replaces the existing data at the path with the new rows
    4. Ddf.write.mode('error').parquet(path), which replaces the existing data after the write has completed successfully
    Show answer and explanation
    Correct answer: C

    overwrite replaces the data at the path with the DataFrame's rows. Append adds rows, ignore skips the write when data exists, and error raises an exception rather than replacing the output.

  3. Question 11

    Which code reads the Delta table registered as sales in the metastore?

    1. Aspark.sql.read('sales')
    2. Bspark.read.csv('sales')
    3. Cdf.load('sales')
    4. Dspark.table('sales')
    Show answer and explanation
    Correct answer: D

    spark.table returns a registered table as a DataFrame by name. Reading CSV from a table name, calling sql.read and calling load on a DataFrame are not valid ways to read a metastore table.

  4. Question 12

    Which two statements about reading and writing data in Spark are correct? (Choose two.)

    1. AParquet is a columnar format that stores schema information with the data, so readers do not need a separate schema
    2. BWriting a DataFrame to a path creates a directory of part files, one per partition, rather than a single file
    3. CSpark always writes a single CSV file, so partitioning the output has no effect on the number of files produced
    4. DReading a JSON file requires a header row, since Spark uses the first row to determine the column names of the data
    5. EThe append mode overwrites the previous data at the path, so repeated writes leave only the latest rows in place
    Show answer and explanation
    Correct answer: A, B

    Parquet embeds its schema and is columnar, and Spark writes one part file per partition into a directory. CSV output also follows partitioning, JSON does not require a header, and append adds rows rather than overwriting.

Spark SQL (4 questions)

  1. Question 13

    Which code registers a DataFrame as a temporary view and queries it with Spark SQL?

    1. Adf.saveAsSQL('sales'); spark.query('SELECT region, SUM(amount) FROM sales GROUP BY region')
    2. Bspark.sql('sales'); df.sql('SELECT region, SUM(amount) FROM sales GROUP BY region')
    3. Cdf.createOrReplaceTempView('sales'); spark.sql('SELECT region, SUM(amount) FROM sales GROUP BY region')
    4. Ddf.registerTable('sales'); df.execute('SELECT region, SUM(amount) FROM sales GROUP BY region')
    Show answer and explanation
    Correct answer: C

    createOrReplaceTempView registers the DataFrame under a name, and spark.sql runs a SQL query against it. The other methods such as saveAsSQL, query, registerTable and execute do not exist as used.

  2. Question 14

    Which statement about Spark SQL and the DataFrame API is correct?

    1. ASpark SQL queries always run slower than DataFrame code, because SQL cannot be optimized by the Catalyst engine at all
    2. BThe DataFrame API can only be used with Python, and Spark SQL can only be used with Scala in production jobs
    3. CSpark SQL queries and DataFrame transformations compile to the same optimized logical plan, so their performance is comparable
    4. DSpark SQL requires a separate cluster from the one that runs DataFrame transformations, so the two cannot be combined
    Show answer and explanation
    Correct answer: C

    Both SQL and the DataFrame API are translated to the same logical plan and optimized by Catalyst, so performance is generally comparable. The other statements reflect misconceptions about the optimizer, languages and clusters.

  3. Question 15

    Which two SQL statements are valid in Spark SQL? (Choose two.)

    1. ASELECT region FROM sales HAVING amount > 100
    2. BSELECT * FROM sales JOIN ON customers.id = sales.customer_id
    3. CSELECT region, COUNT(*) FROM sales GROUP BY region
    4. DSELECT region FROM sales WHERE amount > 100 AND status = 'active'
    5. ESELECT region, SUM(amount) WITHIN sales GROUP BY region
    Show answer and explanation
    Correct answer: C, D

    GROUP BY with COUNT and a WHERE clause with AND are standard Spark SQL. WITHIN is not valid syntax, a JOIN requires a table name before ON, and HAVING without GROUP BY on amount is not valid as written.

  4. Question 16

    Which Spark SQL query uses a common table expression to compute totals first, and then filters on those totals?

    1. ASELECT totals AS (SUM(amount)) FROM sales WHERE total > 500 GROUP BY customer_id ORDER BY totals
    2. BSELECT customer_id FROM sales CTE totals WHERE SUM(amount) > 500 GROUP BY customer_id ORDER BY customer_id
    3. CWITH totals AS (SELECT customer_id, SUM(amount) AS total FROM sales GROUP BY customer_id) SELECT * FROM totals WHERE total > 500
    4. DWITH totals SELECT customer_id, SUM(amount) FROM sales FILTER total > 500 GROUP BY customer_id ORDER BY customer_id
    Show answer and explanation
    Correct answer: C

    WITH defines a named subquery that the main query can reference, which is the common table expression pattern. The other statements misplace aliases, use CTE as a keyword, or filter on aggregates without a subquery.

Performance and caching (4 questions)

  1. Question 17

    A DataFrame is reused in several actions, and its computation is expensive. Which action best reduces repeated work?

    1. ACall coalesce(1) on the DataFrame before each action, so that a single task recomputes the full dataset each time
    2. BCall persist() or cache() on the DataFrame before the first action, so that later actions reuse the stored partitions
    3. CCall collect() on the DataFrame after each transformation, so that every later step starts from a driver copy
    4. DCall repartition(1000) on the DataFrame before each action, so that more tasks share the recomputation work
    Show answer and explanation
    Correct answer: B

    cache or persist stores the computed partitions so that later actions do not recompute the lineage. Collect, coalesce(1) and high repartitioning either move data to the driver or add cost without avoiding recomputation.

  2. Question 18

    Which two actions improve the performance of a Spark job? (Choose two.)

    1. ACollecting the full dataset to the driver before every transformation in the pipeline
    2. BUsing a Python UDF where a built-in function exists, applied to every row of the DataFrame
    3. CFiltering and selecting only the needed columns early in the pipeline, to reduce the data moved
    4. DUsing broadcast joins for small dimension tables that fit in the memory of each executor
    5. ESetting the number of shuffle partitions to 1 for every job, regardless of the size of the data
    Show answer and explanation
    Correct answer: C, D

    Early filtering and column selection reduce the data that later stages handle, and broadcast joins avoid shuffling large tables for small lookups. Collecting to the driver, row-level Python UDFs and a single shuffle partition for all jobs all create bottlenecks.

  3. Question 19

    Which action redistributes the rows of a DataFrame into a set number of partitions using a full shuffle?

    1. Adf.explain(), which prints the physical plan of the DataFrame without changing its partition layout
    2. Bdf.coalesce(200), which reduces the partition count without a shuffle when the number is lower than current
    3. Cdf.repartition(200), which redistributes the rows into 200 partitions using a full shuffle
    4. Ddf.cache(), which stores the existing partitions in memory without changing their number at all
    Show answer and explanation
    Correct answer: C

    repartition performs a full shuffle and can increase or decrease the partition count. Coalesce reduces partitions without a full shuffle, cache does not change partitioning, and explain only prints the plan.

  4. Question 20

    Which method prints the logical and physical plans of a DataFrame, for performance analysis?

    1. Adf.show(), which prints the first rows of the DataFrame as a table in the console output
    2. Bdf.describe(), which computes summary statistics for the numeric columns of the DataFrame
    3. Cdf.printSchema(), which prints the column names and types of the DataFrame as a tree
    4. Ddf.explain(), which prints the logical and physical plans of the DataFrame for inspection
    Show answer and explanation
    Correct answer: D

    explain prints the plans, including the physical plan, for analyzing how Spark will execute the query. Print schema shows types, describe computes statistics, and show prints rows.

Joins and aggregations (4 questions)

  1. Question 21

    Which code computes the total amount per customer_id from a DataFrame sales?

    1. Asales.groupBy('customer_id').agg(sum('amount').alias('total'))
    2. Bsales.select('customer_id').sum('amount')
    3. Csales.groupBy('amount').agg(sum('customer_id'))
    4. Dsales.orderBy('customer_id').sum('amount')
    Show answer and explanation
    Correct answer: A

    groupBy by customer_id followed by agg with sum of amount, aliased as total, gives one total per customer. Selecting then summing does not group, grouping by amount swaps the keys, and orderBy does not aggregate.

  2. Question 22

    Two DataFrames, orders and customers, are joined on customer_id. A customer with no orders must not appear in the result. Which join type produces this?

    1. AAn inner join, which keeps only the rows where customer_id appears in both DataFrames with a match
    2. BA full outer join, which keeps every row from both DataFrames and fills unmatched sides with nulls
    3. CA cross join, which pairs every customer with every order and then filters nothing out of the result
    4. DA left join from customers to orders, which keeps every customer including those without any orders
    Show answer and explanation
    Correct answer: A

    An inner join keeps only keys present in both DataFrames, so customers without orders are excluded. A left join keeps them, a full outer join keeps unmatched rows from both sides, and a cross join creates every combination.

  3. Question 23

    A small dimension table is joined to a very large fact table. Which code avoids shuffling the large table?

    1. Afact.join(dim, 'key').repartition(1), which moves all rows into one partition after the join is complete
    2. Bfact.join(broadcast(dim), 'key'), which sends a copy of the small table to every executor
    3. Cfact.repartition(1).join(dim, 'key'), which combines all fact rows into one partition before the join runs
    4. Dfact.join(dim, 'key').cache(), which stores the joined result in memory for later reuse by queries
    Show answer and explanation
    Correct answer: B

    A broadcast join sends the small table to every executor, which avoids shuffling the large table. Repartitioning to one partition creates a bottleneck, and caching the result does not change how the join is executed.

  4. Question 24

    Which two statements about Spark joins are correct? (Choose two.)

    1. AA left anti join returns the rows from the left DataFrame that have no match in the right DataFrame
    2. BA left semi join returns all columns from both DataFrames for each matching row in the result
    3. CA cross join is the default join type in Spark, so a join without a join type always produces a cross join
    4. DAn outer join never produces null values, since Spark fills every unmatched column with a default value
    5. EJoining on a column name, rather than an expression, keeps only one copy of the join key in the output DataFrame
    Show answer and explanation
    Correct answer: A, E

    A left anti join returns left rows without a match, and joining on column names keeps a single key column. A semi join returns only left columns, an inner join is the default rather than a cross join, and outer joins produce nulls for unmatched values.

Window functions and UDFs (3 questions)

  1. Question 25

    Which code assigns a rank within each department, ordered by salary from highest to lowest?

    1. Adf.withColumn('rnk', rank().over(Window.partitionBy('department').orderBy(col('salary').desc())))
    2. Bdf.withColumn('rnk', rank().over(Window.orderBy('department').partitionBy(col('salary'))))
    3. Cdf.withColumn('rnk', rank(partitionBy='department', orderBy='salary'))
    4. Ddf.groupBy('department').withColumn('rnk', rank())
    Show answer and explanation
    Correct answer: A

    A window partitioned by department and ordered by salary descending, applied with rank over, gives the rank per department. The other forms swap partition and order, call withColumn on grouped data, or pass arguments that rank does not accept.

  2. Question 26

    Why should a built-in Spark SQL function be preferred over a Python UDF when one exists?

    1. APython UDFs run row by row in Python, outside the JVM optimizer, so built-in functions are usually much faster
    2. BPython UDFs are always distributed across all executors, which makes them slower than built-in functions that run on the driver
    3. CBuilt-in functions cannot be used with DataFrames, so a UDF is required whenever the operation uses column values directly
    4. DPython UDFs automatically cache their output, which makes repeated calls faster than built-in functions over the same data
    Show answer and explanation
    Correct answer: A

    Python UDFs serialize rows between the JVM and Python and bypass the Catalyst optimizer, so built-in functions are usually faster. The other statements are wrong about where UDFs run, whether built-ins work with DataFrames, and caching.

  3. Question 27

    Which expression gives each row the previous row's amount within each customer, ordered by date?

    1. Alag('amount', 1).over(Window.partitionBy('customer_id').orderBy('date'))
    2. Blead('amount', 1).over(Window.partitionBy('customer_id').orderBy('date'))
    3. Cfirst('amount').over(Window.partitionBy('customer_id'))
    4. Dsum('amount').over(Window.orderBy('date').rowsBetween(-1, 0))
    Show answer and explanation
    Correct answer: A

    lag returns the value from the previous row within the window, and the window partitions by customer and orders by date. Lead returns the next row, first returns the first value in the partition, and a sum over rows does not return the previous amount.

Transformations and actions (3 questions)

  1. Question 28

    Which of the following is an action rather than a transformation?

    1. AwithColumn, which adds or replaces a column computed from an expression in the DataFrame
    2. Bfilter, which keeps the rows that satisfy a condition and returns a new DataFrame
    3. CgroupBy, which groups rows by one or more keys and returns a grouped object for aggregation
    4. Dcount, which triggers computation and returns the number of rows to the driver as a number
    Show answer and explanation
    Correct answer: D

    count is an action because it triggers execution and returns a value to the driver. Filter, groupBy and withColumn are transformations that only build a plan.

  2. Question 29

    Which statement about narrow and wide transformations is correct?

    1. AA narrow transformation, such as filter, needs data from many partitions, so it always causes a shuffle across the cluster
    2. BA wide transformation, such as join, can require data from many partitions, so it usually causes a shuffle
    3. CA wide transformation, such as select, processes each partition independently and never moves data between them
    4. DA narrow transformation, such as groupBy, requires all the rows with a key to be on the same partition
    Show answer and explanation
    Correct answer: B

    Wide transformations such as join need data from many partitions, which causes a shuffle. Filter and select are narrow, and groupBy is the wide transformation that needs key co-location.

  3. Question 30

    Which code returns the number of distinct customer_id values in a DataFrame?

    1. Adf.select(countDistinct('customer_id')).collect()
    2. Bdf.select('customer_id').count()
    3. Cdf.groupBy('customer_id').count().count()
    4. Ddf.agg(count('customer_id').distinct())
    Show answer and explanation
    Correct answer: A

    countDistinct counts distinct values, and collect returns the single result row to the driver. Count after select counts all rows including duplicates, and the other forms do not return a distinct count in the way the requirement describes.