Spark 采样 - 它比使用完整 RDD/DataFrame 快多少
Spark Sampling - How much faster is it than using the full RDD/DataFrame
我想知道在采样 RDD/DF 时 Spark 的运行时间与完整 RDD/DF 的运行时间相比是多少。我不知道它是否有所作为,但我目前正在使用 Java + Spark 1.5.1 + Hadoop 2.6.
JavaRDD<Row> rdd = sc.textFile(HdfsDirectoryPath()).map(new Function<String, Row>() {
@Override
public Row call(String line) throws Exception {
String[] fields = line.split(usedSeparator);
GenericRowWithSchema row = new GenericRowWithSchema(fields, schema);//Assum that the schema has 4 integer columns
return row;
}
});
DataFrame df = sqlContext.createDataFrame(rdd, schema);
df.registerTempTable("df");
DataFrame selectdf = sqlContext.sql("Select * from df");
Row[] res = selectdf.collect();
DataFrame sampleddf = sqlContext.createDataFrame(rdd, schema).sample(false, 0.1);// 10% of the original DS
sampleddf.registerTempTable("sampledf");
DataFrame selecteSampledf = sqlContext.sql("Select * from sampledf");
res = selecteSampledf.collect();
我希望采样速度最佳接近 ~90%。但对我来说,火花似乎穿过整个 DF 或进行计数,这基本上与完整 DF select 花费的时间几乎相同。样本生成后,执行select.
我的这个假设是否正确,或者采样使用的方式不对导致我最终得到两个 select 所需的相同运行时间?
I would expect that the sampling is optimally close to ~90% faster.
嗯,这些期望不切实际有几个原因:
- 在没有任何关于数据分布的假设的情况下,要获得均匀的样本,您必须执行完整的数据集扫描。这或多或少是在 Spark
中使用 sample
或 takeSample
方法时发生的情况
SELECT *
是一个比较轻量级的操作。根据资源量,您有时间处理单个分区可以忽略不计
- 采样不会减少分区数。如果您不使用
coalesce
或 repartition
,您最终会得到大量几乎为空的分区。这意味着次优资源使用。
- 虽然 RNG 通常非常有效,但生成随机数并不是免费的
抽样至少有两个重要的好处:
- 更低的内存使用量,包括更少的垃圾收集器工作
- 在洗牌或收集的情况下序列化/反序列化和传输的数据更少
如果您想从采样中获得最大收益,采样、合并和缓存是有意义的。
我想知道在采样 RDD/DF 时 Spark 的运行时间与完整 RDD/DF 的运行时间相比是多少。我不知道它是否有所作为,但我目前正在使用 Java + Spark 1.5.1 + Hadoop 2.6.
JavaRDD<Row> rdd = sc.textFile(HdfsDirectoryPath()).map(new Function<String, Row>() {
@Override
public Row call(String line) throws Exception {
String[] fields = line.split(usedSeparator);
GenericRowWithSchema row = new GenericRowWithSchema(fields, schema);//Assum that the schema has 4 integer columns
return row;
}
});
DataFrame df = sqlContext.createDataFrame(rdd, schema);
df.registerTempTable("df");
DataFrame selectdf = sqlContext.sql("Select * from df");
Row[] res = selectdf.collect();
DataFrame sampleddf = sqlContext.createDataFrame(rdd, schema).sample(false, 0.1);// 10% of the original DS
sampleddf.registerTempTable("sampledf");
DataFrame selecteSampledf = sqlContext.sql("Select * from sampledf");
res = selecteSampledf.collect();
我希望采样速度最佳接近 ~90%。但对我来说,火花似乎穿过整个 DF 或进行计数,这基本上与完整 DF select 花费的时间几乎相同。样本生成后,执行select.
我的这个假设是否正确,或者采样使用的方式不对导致我最终得到两个 select 所需的相同运行时间?
I would expect that the sampling is optimally close to ~90% faster.
嗯,这些期望不切实际有几个原因:
- 在没有任何关于数据分布的假设的情况下,要获得均匀的样本,您必须执行完整的数据集扫描。这或多或少是在 Spark 中使用
SELECT *
是一个比较轻量级的操作。根据资源量,您有时间处理单个分区可以忽略不计- 采样不会减少分区数。如果您不使用
coalesce
或repartition
,您最终会得到大量几乎为空的分区。这意味着次优资源使用。 - 虽然 RNG 通常非常有效,但生成随机数并不是免费的
sample
或 takeSample
方法时发生的情况
抽样至少有两个重要的好处:
- 更低的内存使用量,包括更少的垃圾收集器工作
- 在洗牌或收集的情况下序列化/反序列化和传输的数据更少
如果您想从采样中获得最大收益,采样、合并和缓存是有意义的。