我已经阅读了有关散列分区的各种文章。但是我仍然无法在什么情况下获得它比范围分区更有利。使用sortByKey后跟范围分区允许数据在集群中均匀分布。但在散列分区中可能不是这种情况。请考虑以下示例:
考虑一对带有键[8,96,240,400,401,800]的RDD,所需的分区数为4。
在这种情况下,散列分区按如下方式分配密钥 分区:
partition 0: [8, 96, 240, 400, 800]
partition 1: [ 401 ]
partition 2: []
partition 3: []
(计算分区:p = key.hashCode()%numPartitions)
上述分区会导致性能下降,因为密钥并非均匀分布在所有节点上。由于范围分区可以在集群中平均分配密钥,那么在什么情况下散列分区被证明最适合范围分区?
答案 0 :(得分:9)
虽然hashCode
的弱点值得关注,尤其是在处理小整数时,通常可以通过根据域特定知识调整分区数来解决。也可以使用更合适的散列函数将默认HashPartitioner
替换为自定义Partitioner
。只要没有数据偏差,散列分区的平均规模就足够好了。
数据偏差是完全不同的问题。如果密钥分发明显偏离,则无论使用何种Partitioner
,分区数据的分发都可能会出现偏差。例如,考虑以下RDD:
sc.range(0, 1000).map(i => if(i < 9000) 1 else i).map((_, None))
根本无法统一分区。
为什么不默认使用RangePartitioner
?
HashPartioner
。虽然HashPartitioner
只需要##
==
和K
RangePartitioner
的正确实施,但Ordering[K]
需要HashPartitioner
。val rdd1 = sc.range(0, 1000).map((_, None))
val rdd2 = sc.range(1000, 2000).map((_, None))
val rangePartitioner = new RangePartitioner(11, rdd1)
rdd1.partitionBy(rangePartitioner).glom.map(_.length).collect
不同,它必须近似数据分布,因此requires additional data scan。因为拆分是根据特定分布计算的,所以在跨数据集重用时可能会不稳定。请考虑以下示例:
Array[Int] = Array(88, 91, 99, 91, 87, 92, 83, 93, 91, 86, 99)
rdd2.partitionBy(rangePartitioner).glom.map(_.length).collect
Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1000)
joins
您可以想象这对val hashPartitioner = new HashPartitioner(11)
rdd1.partitionBy(hashPartitioner).glom.map(_.length).collect
等操作有严重影响。同时
Array[Int] = Array(91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90)
rdd2.partitionBy(hashPartitioner).glom.map(_.length).collect
Array[Int] = Array(91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 91)
const axios = require('axios');
const querystring = require('querystring');
const keys = require('../config/keys');
const getAccessToken = async refreshToken => {
try {
const accessTokenObj = await axios.post(
'https://www.googleapis.com/oauth2/v4/token',
querystring.stringify({
refresh_token: refreshToken,
client_id: keys.googleClientID,
client_secret: keys.googleClientSecret,
grant_type: 'refresh_token'
})
);
return accessTokenObj.data.access_token;
} catch (err) {
console.log(err);
}
};
这让我们回到你的问题:
在什么情况下它比范围分区更有利。
散列分区是许多系统中的默认方法,因为它相对不可知,通常表现得相当好,并且不需要有关数据分布的其他信息。由于缺乏关于数据的任何先验知识,这些属性使其成为可取的。