Skip to main content
Xenors Xenors
Home › Data Science › PySpark DataFrames and Spark SQL for Beginners

Module 12: Big Data Analytics for Data ScienceBy Ashok Kumar Yadav4 min read

PySpark DataFrames and Spark SQL for Beginners

Spark lets you query the same data with SQL or with the DataFrame API. Both compile to the same optimised plan, so choose whichever reads better for the task.

Spark SQL query and DataFrame API producing the same optimised execution plan
Quick answer: Create a DataFrame, register it with createOrReplaceTempView, and run spark.sql('SELECT ...'). The DataFrame API and SQL produce the same Catalyst-optimised plan, so use SQL for readability and the API for programmatic pipelines.

Create DataFrames with an explicit schema

Declaring a schema avoids a slow inference pass and prevents wrong types.

Two small DataFrames
from pyspark.sql import SparkSession, functions as F
from pyspark.sql.types import StructType, StructField, StringType, IntegerType, DoubleType

spark = SparkSession.builder.master("local[*]").appName("sql").getOrCreate()

emp_schema = StructType([StructField("id", IntegerType()), StructField("name", StringType()),
                         StructField("dept_id", IntegerType()), StructField("salary", DoubleType())])
employees = spark.createDataFrame(
    [(1, "Asha", 10, 72000.0), (2, "Ravi", 10, 65000.0), (3, "Meera", 20, 88000.0),
     (4, "Kabir", 20, 91000.0), (5, "Zoya", 30, 54000.0)], emp_schema)
depts = spark.createDataFrame([(10, "Data"), (20, "Engineering"), (40, "Sales")], ["dept_id", "dept"])

Select, filter and join

Join type matters: inner keeps matches only, left keeps all rows from the left side.

DataFrame API operations
(employees.filter(F.col("salary") > 60000)
           .select("name", (F.col("salary") / 12).alias("monthly"))
           .show())

employees.join(depts, "dept_id", "left").show()      # Zoya has no dept -> null
employees.join(depts, "dept_id", "inner").show()

Write the same logic in Spark SQL

Register a temporary view and use ordinary SQL, including window functions.

Ranking salaries inside each department
employees.createOrReplaceTempView("employees")
depts.createOrReplaceTempView("depts")

spark.sql('''
    SELECT d.dept, e.name, e.salary,
           RANK() OVER (PARTITION BY d.dept ORDER BY e.salary DESC) AS rnk,
           AVG(e.salary) OVER (PARTITION BY d.dept) AS dept_avg
    FROM employees e JOIN depts d ON e.dept_id = d.dept_id
''').show()

Read the execution plan

Use explain() to see whether Spark pushes filters down and which join strategy it picked. Small tables can be broadcast to every executor, which avoids an expensive shuffle.

Broadcast join and explain
from pyspark.sql.functions import broadcast
employees.join(broadcast(depts), "dept_id").explain()

Save and reuse

Write results as Parquet, partitioned by a column you often filter on. Spark then reads only the partitions it needs.

Partitioned Parquet output
employees.write.mode("overwrite").partitionBy("dept_id").parquet("out/employees")
spark.read.parquet("out/employees").filter("dept_id = 20").show()

Hands-on practice

Run the examples in the downloadable Jupyter notebook. The extra checks below focus on mistakes that appear in real projects, not just syntax.

Verify a join with explicit keys

Practice example
orders = spark.createDataFrame([(1,10),(2,20)], ['customer_id','amount'])
customers = spark.createDataFrame([(1,'A'),(3,'C')], ['customer_id','name'])
orders.join(customers,'customer_id','left').show()
+-----------+------+----+
|customer_id|amount|name|
+-----------+------+----+
|1          |10    |A   |
|2          |20    |NULL|

A left join preserves every order even when the customer dimension is incomplete.

Read the physical plan

Practice example
q = orders.groupBy('customer_id').sum('amount')
q.explain(mode='formatted')
Physical Plan
+- HashAggregate ...

Use explain() before guessing about Spark performance.

Self-check

  • Can you explain why the first practice result is trustworthy rather than just plausible?
  • What would you monitor or test before using this Spark SQL & DataFrames workflow in production?
  • Which assumption in the example would break first on a larger or messier dataset?

Frequently asked questions

DataFrame API or Spark SQL?

They are equivalent in performance. Use SQL when analysts will read it and the API when building reusable pipeline code.

What is a temporary view?

A name for a DataFrame that lets you query it with SQL inside the current Spark session.

What is a broadcast join?

Spark sends a small table to every executor so the large table does not need to be shuffled.

Primary references

Use these official sources when exact syntax, defaults or definitions matter beyond the examples here.

Written by Ashok Kumar Yadav
Ashok Kumar Yadav writes Xenors tutorials on applied AI, programming and data workflows. Every lesson is built around code you can run and check yourself.
GitHub · LinkedIn

Continue exploring