🎉 75% of content is free forever — Unlock Premium from $10/mo →
CW
💼 Servicesℹ️ About✉️ ContactView Pricing Plansfrom $10

PySpark RDD Fundamentals: Architecture, Transformations, and Actions

PySpark FundamentalsRDD🟢 Free Lesson

Advertisement

PySpark RDD Fundamentals

Narrow vs Wide Transformation Partition Mapping

Narrow (1:1)Wide (N:M Shuffle)P0P1P2P3P0'P1'P2'P3'map, filter, flatMap, unionP0P1P2P3P0'P1'P2'P3'groupByKey, reduceByKey, join, repartitionShuffle Barrier: data written to disk, transferred across network, read by reducer

RDD Lineage Fault Tolerance

textFile()map()filter()reduceByKey()collect()Lineage: If P2 of reduceByKey lost → recompute only P2 from source → map → filter → reduceByKey

RDD Architecture Overview

RDD Transformation DAG

Narrow vs Wide Transformations

Code Examples

Basic RDD Operations

from pyspark import SparkContext, SparkConf

conf = SparkConf().setAppName("RDD_Basics").setMaster("local[*]")
sc = SparkContext(conf=conf)

# Create RDD from collection
data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
rdd = sc.parallelize(data, 4)  # 4 partitions
print(f"Partitions: {rdd.getNumPartitions()}")

# Narrow transformations (no shuffle)
mapped = rdd.map(lambda x: x * 2)
filtered = rdd.filter(lambda x: x > 5)
flattened = rdd.flatMap(lambda x: [x, x * 10])

# Wide transformation (shuffle)
pairs = rdd.map(lambda x: (x % 3, x))
grouped = pairs.groupByKey()
reduced = pairs.reduceByKey(lambda a, b: a + b)

# Actions (trigger execution)
print(f"Count: {rdd.count()}")
print(f"First: {rdd.first()}")
print(f"Take: {rdd.take(3)}")
print(f"Sum: {rdd.reduce(lambda a, b: a + b)}")

# Check lineage
print(rdd.toDebugString().decode())

sc.stop()

RDD Persistence Levels

from pyspark import StorageLevel

# Cache in memory (deserialized)
rdd.cache()  # Equivalent to persist(StorageLevel.MEMORY_ONLY)

# Persist with specific storage level
rdd.persist(StorageLevel.MEMORY_AND_DISK)
rdd.persist(StorageLevel.MEMORY_ONLY_SER)
rdd.persist(StorageLevel.DISK_ONLY)
rdd.persist(StorageLevel.OFF_HEAP)

# Unpersist when done
rdd.unpersist()

Key Concepts Table

ConceptDescriptionExample
PartitionLogical chunk of data for parallel processingrdd.getNumPartitions()
LineageDAG of transformations for fault tolerancerdd.toDebugString()
Narrow Transform1:1 partition mapping, no shufflemap(), filter(), flatMap()
Wide TransformM:N partition mapping, requires shufflegroupByKey(), reduceByKey(), join()
Lazy EvaluationTransforms built but not executed until actionBuild DAG → Action triggers execution
ActionTriggers computation, returns resultcollect(), count(), first()
Cache/PersistStore RDD in memory/disk for reuserdd.cache() or rdd.persist()
CheckpointWrite RDD to reliable storage, truncate lineagerdd.checkpoint()
BroadcastRead-only variable cached on each executorsc.broadcast(variable)
AccumulatorWrite-only variable for aggregationssc.accumulator(0)

Best Practices

  1. Prefer DataFrames over RDDs — DataFrames use Catalyst optimizer and Tungsten engine for automatic optimization
  2. Use reduceByKey over groupByKeyreduceByKey combines locally before shuffle, reducing network I/O
  3. Cache wisely — Only cache RDDs that are reused across multiple actions
  4. Partition appropriately — Aim for 128MB–200MB per partition
  5. Avoid collect() on large datasets — use take(n) or foreach() instead
  6. Use coalesce() to reduce partitions — avoids full shuffle unlike repartition()
  7. Enable Kryo serialization — 10x faster than Java serialization
  8. Monitor shuffle spill — indicates memory pressure

Key Takeaways

See Also

Need Expert PySpark Help?

Get personalized tutoring, project support, or professional consulting.

Advertisement