> For the complete documentation index, see [llms.txt](https://docs.datahungry.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.datahungry.dev/library/pyspark.md).

# Pyspark

## Setup spark

1. Download Spark from official website <https://spark.apache.org/downloads.html>
2. Setup environment

<figure><img src="https://3744479106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLJiDkWvKdN4dP8wNg15P%2Fuploads%2FDGJwYcQls8VmvfiFTgSI%2Fimage.png?alt=media&amp;token=67a6c1a7-48ae-49b8-a14a-4c5a9770b9ce" alt=""><figcaption><p>Download Spark</p></figcaption></figure>

{% code title="Setup Environment" %}

```
HADOOP_HOME=C:\Winutils
JAVA_HOME=C:\Program Files\Java\jdk1.8.0_202
SPARK_HOME=C:\Users\<NAME>\Documents\spark-3.5.0-bin-hadoop3
Path=%HADOOP_HOME%\bin
Path=%JAVA_HOME%\bin
Path=%SPARK_HOME%\bin
```

{% endcode %}

***

## Connect Spark

```
spark-shell
```

## Spark Architecture

<figure><img src="https://3744479106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLJiDkWvKdN4dP8wNg15P%2Fuploads%2FwcGYvzah5ADm3AFdRDae%2Fimage.png?alt=media&amp;token=7dbf748e-bea8-4c65-820d-1287dfcbb395" alt=""><figcaption><p>Spark Architectire</p></figcaption></figure>

## Concept

### Lazy Evaluation

Evaluation strategy that delays the evaluation of an expression until its value is needed

### Transformations

* **Narrow:** can be done within a single partition ex. map(), filter(), union()
* **Wide:** need to be combined data from all partitions ex. groupByKey(), reduceByKey(), join()

### Catalyst Optimizer

<figure><img src="https://3744479106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLJiDkWvKdN4dP8wNg15P%2Fuploads%2FmSgUVZIu760NXiq6DdQ9%2Fimage.png?alt=media&amp;token=00212c07-c61c-488c-8a21-fed21e659339" alt=""><figcaption></figcaption></figure>

* Analysis
* Logical optimization
* Physical planning
* Code generation

### Tungsten Binary Format (Unsafe Row)

Tungsten Binary Format is data sharing optimization in shuffle step

* Data shuffle creates **stage** boundary
* Spark can execute a process **backwards**
* The **cache** process works like shuffle files

### Application

<figure><img src="https://3744479106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLJiDkWvKdN4dP8wNg15P%2Fuploads%2F1k8cP4YV8VBhIaQzrG3e%2Fimage.png?alt=media&amp;token=8cc959e6-16f8-4a0e-b8fc-daedaac9ec46" alt=""><figcaption><p>Job, Stage, and Task</p></figcaption></figure>

* **Job:** a sequence of transformations on data. ex count(), first(), collect(), save(), read(), write(), take()
* **Stage:** a job is divided into stages by shuffling
* **Task:** smallest unit of work. Each stage is divided into tasks. Execute on executors parallely. Operation over a single partition of data

<figure><img src="https://3744479106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLJiDkWvKdN4dP8wNg15P%2Fuploads%2F7AgywwFNV9WWTb1DJ0bo%2Fimage.png?alt=media&amp;token=99889ac5-90a3-4d5a-845b-d500a418f521" alt=""><figcaption><p>Stage and Shuffle</p></figcaption></figure>

### Memory

<figure><img src="https://3744479106-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLJiDkWvKdN4dP8wNg15P%2Fuploads%2F48LiorQTdjpDtNUwRCMm%2Fimage.png?alt=media&amp;token=4d6604a8-7d16-4dbe-8f41-e9f1c1c51e14" alt=""><figcaption></figcaption></figure>

#### Type of Memory

* **Driver Memory:** the memory assigned to the driver process used for creating execution plans, tracking data, and gathering results.
* **Execurtor Memory**: the amount of memory allocated to each executor process
  * **Reserved Memory:** the memory reserved by the system 300MB that cannot be changed. If executor memory less than 1.5 times of reserved memory (450MB), it will be failed
  * **User Memory:** stores all the user defined data structures, UDFs
  * **Spark Memory:** This is responsible for storing intermediate state while doing task execution, cache/persisted data
    * **Storage Memory**: used for storing all of the cached data, broadcast variable
    * **Execution Memory**: used by Spark for objects created during execution of task

#### Calulation

<mark style="color:green;">Reserved Memory</mark> = 300 MB

User Memory = (java heap - <mark style="color:green;">Reserved Memory</mark>) \* (1- <mark style="color:blue;">spark.memory.fraction</mark>)

<mark style="color:orange;">Spark Memory</mark> = (java heap - <mark style="color:green;">Reserved Memory</mark>) \* <mark style="color:blue;">spark.memory.fraction</mark>

Storage Memory = <mark style="color:orange;">SparkMemory</mark> \* <mark style="color:purple;">spark.memory.storageFraction</mark>

Execution Memory = <mark style="color:orange;">SparkMemory</mark> \* (1-<mark style="color:purple;">spark.memory.storageFraction</mark>)

## Coding

### quick start

```python
from pyspark import SparkConf, SparkContext
from pyspark.sql import SparkSession, functions as F

sc = SparkContext.getOrCreate()
sc.addPyFile(path)
spark = SparkSession.builder.appName("MyApp").getOrCreate()

df = spark.sql(“SELECT * FROM bd.tbl_name”)

df = df.withColumn("month", F.month('data_dt'))
df = df.filter(F.col("month") > 6))

df.write.partition('data_dt').saveAsTable(tbl_name, mode=“overwrite”)
```

### Data Type

```python
from pyspark.sql.types import StringType, DateType

col_name = 'data_dt'
if isinstance(df.schema[col_name].dataType, StringType):
    pass
```

### Functions&#x20;

```
concat_ws
current_timestamp
lit
col
to_timestamp
date_format
add_months
year
month
quarter
when
substring
split
regexp_replace
lpad
rpad
sha2
to_date
last_day
```

###

### Transform

```python

df.withColumnRenamed(old_name, new_name)
df.withColumn(new_name, fun_name())

df.filter(col().isNotNull())
col().cast(“timestamp”)
when(col() > 2000, 100).otherwise(col())

df = df1.join(df2, on='id', how='inner')
```

### Write

#### Insert into

* overwrite (static): overwrite table
* overwrite (dynamic): overwrite by partition

```python
df.write.insertInto(tbl_name, overwrite=True)
```

#### saveAsTable

overwrite table

```python
df.write.partitionBy(key).saveAsTable(tbl_name, mode=“overwrite”)
```

#### Create if not exists table

```python
if spark._jsparkSession.catalog().tableExists(tbl_name):
   df.write.insertInto(tbl_name, overwrite=True)
else:
   df.write.partition(key).saveAsTable(tbl_name, mode=“overwrite”)
```

## WIndow Analytics

```python
from pyspark.sql.window import Window

df = spark.sql("SELECT * FROM db_nm.tbl_nm")
window_spec = Window.partitionBy("period").orderBy(F.asc("data_dt"))
df = df.withColumn("row_num", F.row_number().over(window_spec))
```

## Configuration

### Dynamic Partition

```python
spark.conf.set("spark.sql.sources.partitionOverwriteMode", "dynamic")
```

### Memory

```python
spark.conf.set("spark.driver.memory", "2g")
spark.conf.set("spark.driver.memoryOverhead", "384m")
spark.conf.set("spark.executor.memory", "4g")
spark.conf.set("spark.executor.memoryOverhead", "512m")
```

## References

* <https://spark.apache.org/docs/latest/configuration.html>
* <https://towardsdatascience.com/3-reasons-why-sparks-lazy-evaluation-is-useful-ed06e27360c4>
* <https://stackoverflow.com/questions/42263270/what-is-the-concept-of-application-job-stage-and-task-in-spark>
* <https://medium.com/@diehardankush/what-are-job-stage-and-task-in-apache-spark-2fc0d326c15f>
* <https://medium.com/analytics-vidhya/apache-spark-memory-management-49682ded3d42>
* <https://www.linkedin.com/pulse/roles-driver-memory-executor-spark-impact-big-data-processing-dip/>
* <https://www.databricks.com/glossary/catalyst-optimizer>
