spark对同一个RDD执行多次算法的默认原理:每次对一个RDD执行一个算子操作时,都会重新从源头处计算一遍。如果某一部分的数据在程序中需要反复使用,这样会增加时间的消耗。
为了改善这个问题,spark提供了一个数据持久化的操作,我们可通过persist()或cache()将需要反复使用的数据加载在内存或硬盘当中,以备后用。
以下是一个基于pyspark计数的测试
#-*- encoding='utf-8' -*-
from pyspark.sql import SparkSession
import time
from pyspark import StorageLevel
spark = SparkSession \
.builder \
.appName('test') \
.getOrCreate()
data = spark.read.csv("hdfs:///user/sparknode/input/test_repartition/*",header=True).cache()
t1 = time.time()
print(data.count())
t2 = time.time()
print(t2-t1)
print(data.count())
t3 = time.time()
print(t3-t2)
print(data.count())
t4 = time.time()
print(t4-t3)
#该输出结果为
29999990
108.410
29999990
6.730
29999990
1.391
#如果没加持久化操作cache(),结果为
29999990
37.553783655166626
29999990
38.87501883506775
29999990
38.92804193496704
从结果可以看出,
未加cache()时,每一次计数操作所用的时间都一样,是否可说明,spark在每一个action结束后都将数据释放了?然后,下次action需要再重新读取。
加cache()后,第二第三次计数所用的时间明显下降,但第一次计数所用的时间却比正常的多,这说明cache()操作本身需要消耗一定的时间,怎么权衡就看实际情况了。
persist()与cache()操作
我们可在读取数据或transform之后连续的调用perisist()或cache()进行数据持久化。
如
data = spark.read.csv("hdfs:///user/sparknode/input/test_repartition/*",header=True) \
.persist(storageLevel=StorageLevel(False,True,False,False,1))
持久化操作可以将数据加载在内存或硬盘中,也可以备份多份,减少数据丢失后重新计算的时间。
采用persist()时,需要先载入StorageLevel方法,该方法主要用于持久化策略的选择
from pyspark import StroageLevel
#参数
StorageLevel(useDisk, useMemory, useOffHeap, deserialized, replication=1)
useDisk 是否使用硬盘
useMemory 是否使用内存
replication 备份份数
#_ser是采用了序列化存储方式,从而减小持久化带来的内存消耗
DISK_ONLY = StorageLevel(True, False, False, False, 1)
DISK_ONLY_2 = StorageLevel(True, False, False, False, 2)
MEMORY_AND_DISK = StorageLevel(True, True, False, False, 1)
MEMORY_AND_DISK_2 = StorageLevel(True, True, False, False, 2)
MEMORY_AND_DISK_SER = StorageLevel(True, True, False, False, 1)
MEMORY_AND_DISK_SER_2 = StorageLevel(True, True, False, False, 2)
MEMORY_ONLY = StorageLevel(False, True, False, False, 1)
MEMORY_ONLY_2 = StorageLevel(False, True, False, False, 2)
MEMORY_ONLY_SER = StorageLevel(False, True, False, False, 1)
MEMORY_ONLY_SER_2 = StorageLevel(False, True, False, False, 2)
OFF_HEAP = StorageLevel(True, True, True, False, 1)
而cache()实际上是调用了persist()方法,并选择了持久化策略为 storageLevel=StorageLevel(True, True, False, False, 1)
即 .cache()与.persist(storageLevel=StorageLevel(True, True, False, False, 1))效果是一样的,都是MEMORY_AND_DISK持久化策略。