intermediate

Parquet

10 min readLast updated: 2026-07-08

Overview

Parquet is the standard binary columnar storage format for Big Data. Learn how it compresses datasets, stores metadata, and optimizes reading speeds in Spark.

What You Will Learn

In this lesson, you will learn:
  • Columnar Format: Why storing columns together is faster than row-based files.
  • Compression: How Snappy and zstd compress binary data.
  • Pruning Optimization: How metadata enables column and partition pruning.

Detailed Concept Explanation

Unlike CSV or JSON, which store data in rows, Apache Parquet stores data in columns.

Why Columnar Storage?

  • Query speed: If a table has 100 columns but your query only selects 2 (SELECT age, country), Spark only reads the bytes for those 2 columns, skipping the other 98. This is called Column Pruning.
  • Excellent compression: Because a column contains values of the same data type, algorithms can compress it far more efficiently than mixed row-based text. By default, Spark compresses Parquet using Snappy.
  • Self-describing: Parquet files contain schema details and summary statistics (like min/max values) in their footer, allowing Spark to skip reading entire row groups if they do not match filter conditions (called Predicate Pushdown).

Code Examples

Input Dataset Preview

Below is the log records dataset:

idlevel
1INFO
2WARN

Python (PySpark) Implementation

python
from pyspark.sql import SparkSession

spark = SparkSession.builder.appName("ParquetTest").getOrCreate()
data = [(1, "INFO"), (2, "WARN")]
df = spark.createDataFrame(data, ["id", "level"])

# Write to Parquet (Snappy compression is default)
df.write.format("parquet").mode("overwrite").save("logs.parquet")

# Read Parquet
read_df = spark.read.format("parquet").load("logs.parquet")
read_df.show()

Expected Output

text
+---+-----+
| id|level|
+---+-----+
|  1| INFO|
|  2| WARN|
+---+-----+

Execution Plan Diagram (Python & Scala)

Execution Plan Diagram
SparkSession.builder
createDataFrame
write.format(parquet)
read.format(parquet)
show()

Scala Implementation

scala
import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder().appName("ParquetScala").getOrCreate()
import spark.implicits._

val df = Seq((1, "INFO"), (2, "WARN")).toDF("id", "level")
df.write.format("parquet").mode("overwrite").save("logs.parquet")

val readDF = spark.read.format("parquet").load("logs.parquet")
readDF.show()

Expected Output

text
+---+-----+
| id|level|
+---+-----+
|  1| INFO|
|  2| WARN|
+---+-----+

SQL Implementation

sql
-- Query a local Parquet directory directly in SQL
SELECT * 
FROM parquet.`logs.parquet`
WHERE level = 'WARN';

Expected Output

Executing this SQL query returns:

idlevel
2WARN

Common Mistakes

  • Checking Schema via Pre-scan: Assuming reading Parquet requires setting inferSchema=True. Parquet files store their schema natively in their metadata, making pre-scans unnecessary.

Best Practices

  • Dynamic Partition Pruning: Partition your Parquet data on disk by directories (e.g. year=2026/month=07) using .partitionBy() to let Spark skip reading folders that do not match filters.

Interview Perspective

What are Column Pruning and Predicate Pushdown in Spark?
  1. Column Pruning: Spark only reads the columns requested by a query, skipping unrequested fields.
  2. Predicate Pushdown: Spark pushes filter conditions down to the file level, reading only the row groups that match the column statistics (min/max values) stored in the Parquet metadata footer, saving disk I/O.

Interactive Challenges

Challenge 1: Write Parquet (Beginner)

Write a PySpark statement to save a DataFrame df to a directory 'data.parquet' in parquet format with overwrite mode.

Related Topics