产生背景:在Spark中,每次任务执行时,都需要将变量从驱动程序发送到每个执行器。如果变量很大,这将导致网络传输和内存开销的增加,从而影响任务的性能。
原理:广播变量可以将变量仅发送一次,然后在每个执行器上缓存,以便多个任务可以共享同一个变量,从而减少了网络传输和内存开销,提高了任务的性能。
# 代码实现
#1.将本地list标记成广播变量即可
broadcast =sc. broadcast(stu_info_list)
#2.使用广播变量,从broadcast对象中取出本地list对象即可
value = broadcast.value
#也就是先放进去broadcast内部,然后从broadcast内部在取出来用,中间传输的是broadcast这个对象了
#只要中间传输的是broadcast对象,,spark就会留意,只会给每个Executor发一份了,而不是傻傻的哪个分区要都给.
#cording:utf8
from pyspark import SparkConf,SparkContext
if __name__ == '__main__':
conf = SparkConf().setMaster('local[*]').setAppName('test')
sc = SparkContext(conf=conf)
stu_info_list = [(1, "张大仙", 11),
(2, '王晓晓', 13),
(3, '张甜甜', 11),
(4, '王大力', 11)]
# 1.将数据封装为广播变量
broadcast = sc.broadcast(stu_info_list)
score_info_rdd = sc.parallelize([
(1, '语文', 99),(2, '数学', 99), (3, '英语', 99), (4, '编程', 99),
(1, '语文', 99), (2, '编程', 99), (3, '语文', 99), (4, '英语', 99),
(1, '语文', 99), (3, '英语', 99), (2, '编程', 99)])
def rdd_func(data):
id = data[0]
name = ''
'''使用id匹配名字'''
'''使用广播变量'''
for stu_info in broadcast.value:
if id == stu_info[0]:
name = stu_info[1]
return name, data[1], data[2]
print(score_info_rdd.map(rdd_func).collect())
'''
场景:本地集合对象 和 分布式集合对象(RDD) 进行关联的时候(如果使用join进行操作,会产生大量shuffle,从而降低分布式集群性能)
需要将本地集合对象封装为广播变量
作用:
可以节省:
1.网络IO的次数
2.Executor的内存占用
'''
需求:想要对map算子计算中的数据,进行计数累加,得到全部数据计算完后的累加结果。
#cording:utf8
from pyspark import SparkConf,SparkContext
if __name__ == '__main__':
conf = SparkConf().setMaster('local[*]').setAppName('test')
sc = SparkContext(conf=conf)
rdd = sc.parallelize((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
# 未使用累加器
count = 0
def count_func(data):
global count
count +=1
print("当前计算次数为;", count)
rdd.map(count_func).collect()
print('计算总数为:', count)
使用累加器代码:
#cording:utf8
from pyspark import SparkConf,SparkContext
if __name__ == '__main__':
conf = SparkConf().setMaster('local[*]').setAppName('test')
sc = SparkContext(conf=conf)
rdd = sc.parallelize((1, 2, 3, 4, 5, 6, 7, 8, 9, 10))
# 使用累加器 注意使用累加器时通过血统关系调用也会计入总数中
count = sc.accumulator(0)
def count_func(data):
global count
count += 1
print("当前计算次数为;", count)
rdd.map(count_func).collect()
print('计算总数为:', count)