Study guide
7.3 Schema Inspection, Row Iteration, and List Conversion
Databricks Certified Associate Developer for Apache Spark — Free Study Guide 2026 Exam
Track your progress as you read
Finished sections get a check mark.
1 Chapter 1: Spark Architecture and Execution
1.1 Spark Benefits, Modules, and DataFrame/Dataset Concepts 1.2 Driver, Executors, and Cluster Managers 1.3 Execution Hierarchy: Applications, Jobs, Stages, and Tasks 1.4 Lazy Evaluation, Transformations vs Actions, and Resilient Lineage
2 Chapter 2: Shuffles, Memory and Persistence
2.1 Narrow vs Wide Dependencies and the Shuffle Mechanism 2.2 Memory Management, Fault Tolerance, and Garbage Collection 2.3 Caching, Persistence, and StorageLevels
3 Chapter 3: Spark SQL Sessions, Tables and Views
3.1 SparkSession, Catalogs, Databases, and Namespaces 3.2 Managed vs External Tables and CTAS 3.3 Views: Temporary vs Global Temporary Views
4 Chapter 4: SQL Sources and Stored Layout
4.1 JDBC Reads, Writes, and Parallelism 4.2 Direct File SQL, Save Modes, and Persistent Layout
5 Chapter 5: SQL Queries and Analytics
5.1 SQL Queries, CTEs, Subqueries, and Built-in Expressions 5.2 Built-in SQL Expressions and an Integrated Query 5.3 Window Functions and Complex Joins in Spark SQL 5.4 SQL Join Semantics and Integrated Analytics
6 Chapter 6: DataFrame Construction and Columns
6.1 DataFrame Construction, Schemas, and StructTypes 6.2 Column Operations: Selecting, Renaming, Deriving, and Casting 6.3 Complex Nested Types and User-Defined Functions
7 Chapter 7: DataFrame Validation and Inspection
7.1 Row Operations: Filtering, Sorting, and Deduplication 7.2 Handling Missing and Null Data 7.3 Schema Inspection, Row Iteration, and List Conversion
8 Chapter 8: Aggregations and Dates
8.1 Grouping, Multi-Dimensional Aggregations, and Pivoting 8.2 Dates, Unix Epoch, and Time-Zone Conversions
9 Chapter 9: DataFrame Joins and File IO
9.1 DataFrame Joins and Combining Datasets 9.2 Data Sources, SaveModes, and Partitioning
10 Chapter 10: Shared Variables and Stateful Processing
10.1 Broadcast Variables, Accumulators, and Closures 10.2 Stateless UDFs, Stateful Operators, and StateStores
11 Chapter 11: Troubleshooting and Tuning
11.1 Diagnosing Performance with the Spark UI & Execution Plans 11.2 Data Skew and Partition Tuning: repartition vs coalesce 11.3 Join Optimization and Broadcast Hash Joins
12 Chapter 12: Structured Streaming
12.1 Streaming Architecture, Sources, and Sinks 12.2 Output Modes, Triggers, and Checkpointing 12.3 Event-Time Processing, Watermarking, and Windowing 12.4 Streaming Deduplication With and Without Watermarks
13 Chapter 13: Spark Connect and Deployment
13.1 Spark Connect Architecture & Client-Server Decoupling 13.2 Working with Spark Connect: Connections and Best Practices
14 Chapter 14: Pandas API on Spark
14.1 Pandas API on Apache Spark: Core Architecture and Syntax 14.2 Pandas-on-Spark Operations, Indexing, and Optimization
7.3 Schema Inspection, Row Iteration, and List Conversion
Key Takeaways Explain This Topic AI
printSchema prints and returns None; schema is a StructType property and columns/dtypes are local metadata.
collect returns a local list of Row objects; toLocalIterator consumes rows incrementally but can still need memory for a large partition.
Use explicit sorting and tie breakers when a bounded sample must be deterministic.
foreach runs task-side code and is unsuitable for populating a driver-side Python list.
Last updated: October 2026
Inspect structure before values
Exam questions often mix a schema operation with an action. A DataFrame has named SQL columns and a plan; it is not a local list of dictionaries. Read the method's return type and purpose before deciding whether it prints, returns metadata, requests distributed results or builds another DataFrame. from pyspark.sql import functions as F
- people = spark.createDataFrame(
- [(2, "Bo", None), (1, "Ari", 20), (3, "Cy", 30)],
- "id INT, name STRING, score INT"
- )
- people.printSchema()
- schema_object = people.schema
- column_names = people.columns
- name_type_pairs = people.dtypes
printSchema() prints a schema tree and returns None. schema is a StructType property, not a method called schema(). columns is a list of names; dtypes is a list of name/type-string pairs. Neither columns nor dtypes provides the actual column values. A local dictionary can map field names to types when needed, but it does not validate every record's business meaning. A reader may have already performed schema discovery, so "metadata inspection" does not imply the source was never contacted.
Display versus return
- API Result in Python Main caution
- show(n) None; prints a table Preview may truncate text unless configured
- take(n) List of at most n Rows Bound result width as well as row count
- first() One Row, or None for empty data No stable first row without ordering
- head(n) List when n supplied head() without n has a different scalar shape
- collect() List of all Rows Entire result must fit local memory/limits
- limit(n) New DataFrame A transformation, not a returned row list
Calling print(people.show()) prints the table and then None. Calling rows = people.limit(2) stores a DataFrame, not two Python rows. A question asking for a list of rows requires an action such as take or collect on a bounded result. A question asking for another distributed DataFrame instead needs a transformation.
- Deterministic small conversion ordered = people.orderBy(F.col("score").desc_nulls_last(), F.col("id").asc())
- rows = ordered.limit(2).collect()
- row_dicts = [row.asDict(recursive=True) for row in rows]
- name_scores = [(row["name"], row["score"]) for row in rows]
- # name_scores -> [("Cy", 30), ("Ari", 20)]
The explicit tie breaker id makes the selected order stable if it is unique. A sort by score alone leaves equal-score ordering unspecified. dropDuplicates followed by a sort cannot recover a particular duplicate row already discarded; use row_number over a fully specified window when survivor identity matters. Null ordering is explicit here rather than inferred from an API default.
Row supports field access by name and positional access, but duplicate column names after a join can make conversion ambiguous. Resolve the schema first by joining on named shared keys or selecting aliased columns. asDict(recursive=True) converts nested Row objects to dictionaries, but does not remove array/map values or turn arbitrary complex data into a flat CSV representation. Choose a deliberate serialization format for external consumers.
Iteration and memory
For a result too large for one Python list, toLocalIterator() returns an iterator consumed in the driver/client process. In classic Spark, its memory usage can include the largest partition; prefetching may include another partition. It is not a distributed Python loop with unlimited memory safety. One enormous partition can still cause trouble, and issuing a separate external request for every iterated row may be very slow. for row in people.select("id", "name").toLocalIterator():
print(row["id"], row["name"])
This is suitable only for an intentionally manageable local consumer. Use distributed writes for large outputs. toPandas() also collects the full distributed result locally, even with Arrow enabled. Arrow can reduce conversion overhead but does not change the single-machine memory requirement. Under Connect, the receiving process is the client rather than necessarily the remote driver, so assess client memory as well.
Task-side iteration is a different tool
foreach and foreachPartition apply functions in task execution. They do not return a list of processed rows to the driver, and appending to a driver list in those functions does not create shared mutation. foreachPartition can initialize a connection once per task partition instead of once per row, but retries can repeat side effects. Use idempotent writes and consider whether an existing DataFrameWriter connector already handles the target more clearly.
Sorting does not determine concurrency: a dataset with many partitions can still run only as many simultaneous tasks as allocated task slots permit. Conversely, collecting just ten rows does not mean every upstream operation is cheap; an upstream global aggregation or join may still process the entire input. Limit the data logically and inspect the physical plan when cost matters.
Round trip and validation
A small local sequence can become a DataFrame with spark.createDataFrame(sequence, explicit_schema). Local input must fit memory before it is distributed, and the schema should match Python value representations. Empty or all-null collections often require explicit types. Compare expected row count, nullable fields and ordering after a round trip; constructing a new DataFrame from a list does not preserve the original partitioning or sorted presentation contract automatically.
See DataFrame API . For an exam code fragment, name the exact returned object at every step and locate where data crosses from distributed execution into a local collection. That habit prevents confusing schema metadata, lazy transformations and eager actions.