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
  • 中使用 sampletakeSample 方法时发生的情况
  • SELECT *是一个比较轻量级的操作。根据资源量,您有时间处理单个分区可以忽略不计
  • 采样不会减少分区数。如果您不使用 coalescerepartition,您最终会得到大量几乎为空的分区。这意味着次优资源使用。
  • 虽然 RNG 通常非常有效,但生成随机数并不是免费的

抽样至少有两个重要的好处:

  • 更低的内存使用量,包括更少的垃圾收集器工作
  • 在洗牌或收集的情况下序列化/反序列化和传输的数据更少

如果您想从采样中获得最大收益,采样、合并和缓存是有意义的。