πŸŽ‰ 75% of content is free forever β€” Unlock Premium from $10/mo β†’
CW
Search courses…
πŸ’Ό 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 groupByKey β€” reduceByKey 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