Spark编程指南之六:RDD Partition分区


数据量很大时,单个节点无法完全存储和计算,需要分割成多个数据块Block,Spark自动对RDD中的大量元素进行分区,并分配给Worker节点做计算。Spark的分区是逻辑上的分区。执行过程中有多少个Task是由RDD分区决定的。同时运行几个Task是由分配给Executor的Core的数量决定的。

RDD Partition属性

partitions

返回包含RDD所有分区引用的一个数组

partitions.size

返回RDD的分区数量

partitioner

返回下列之一:None、HashPartitioner、RangePartitioner、CustomPartitioner(自定义分区器)
分区数量在集群环境读取HDFS文件时,由数据的block个数决定,最小为2。

RDD的初始分区

spark.default.parallelism

spark默认并行度可以推算出RDD的分区数。
如果SparkConf中设置了 spark.default.parallelism那么spark.default.parallelism就等于设置的值。一般设置为Executor的core的总数的2-3倍。如executorsexecutor-cores3
如果没有设置
1)Local模式下:local = 1
local[4] = 4
2 ) Yarn和Standalone模式下:
等于所有Executor能使用的core的总数

通过RDD产生方式计算RDD分区数

第一种方式:集合创建。分区数=spark.default.parallelism

val rdd = sc.parallelize(1 to 100)

第二种方式:从HDFS读取。分区数=HDFS文件的block数
第三种方式:通过已有RDD生成。分区数遵循遗传特性。

有多少个分区是合适的?

从HDFS上读取的文件分区数可以在后续进行重分区。
分区太少会有空闲资源没有利用,容易产生数据倾斜;
分区太多会有频繁的资源切换,任务调度可能比执行时间还长。
一般设置为可用core数量的2-3倍,如executorsexecutor-cores3。
(大数据集群配置:CPU核心数36-48、内存128M或256M)

Spark分区器

Spark有两种分区器:HashPartitioner和RangePartitioner。

HashPartitioner

基于key.hashcode()实现,保证正数。

public class HashPartitioner<K2, V2> implements Partitioner<K2,V2> {
	public HashPartitioner(){
	}
	public void configure(JobConf job){
	}
	public int getPartition(K2 key, V2 value, int numReduceTasks){
		return (key.hashCode() & 2147483647) % numReduceTasks;
	}
}

RangePartitioner

如果有可排序的记录,将根据key对记录排序,然后根据范围划分。

代码示例

rdd.partitionby(new HashPartitioner(4)).saveAsTextFile("out/hashPartition4")

关于减少分区,有需要在filter之后(有空的Partition)进行重分区。

rdd.coalesce(2).saveAsTextFile("out/hashPartition2")

coalesce只能减少分区,coalesce对性能做了优化,尽可能减少shuffle。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值