Spark分组数据的并行处理

时间:2016-04-20 06:40:07

标签: apache-spark apache-spark-sql apache-spark-mllib scala-breeze

最初,我有很多数据。但是使用spark-SQL,尤其是groupBy,它可以减少到可管理的大小。 (适合单个节点的RAM)

我如何在所有组上执行功能(并行)(在我的节点之间分配)?

如何确保将单个组的数据收集到单个节点?例如。我可能希望使用local matrix进行计算,但不希望遇到有关数据局部性的错误。

2 个答案:

答案 0 :(得分:2)

假设你有x不。执行程序(在你的情况下,每个节点可能有1个执行程序)。并且你想要对密钥上的数据进行分区,使得每个密钥都落入一个独特的存储桶,这将是一个完美的分区器。这将是没有通用的方式这样做但如果有一些特定于您的数据的固有分布/逻辑,则可能实现这一点。

          我已经处理了一个特定的案例,我发现Spark的内置散列分区器没有很好地统一分配密钥。所以我用这样的Guava编写了一个自定义分区器:

  class FooPartitioner(partitions: Int) extends org.apache.spark.HashPartitioner(partitions: Int) {
    override def getPartition(key: Any): Int = {
      val hasherer = Hashing.murmur3_32().newHasher()
      Hashing.consistentHash(
        key match {
          case i: Int => hasherer.putInt(i).hash.asInt()
          case _ => key.hashCode
          },PARTITION_SIZE)
  }
 }

然后我将这个分区实例添加为我正在使用的combineBy的参数,以便以这种方式对结果rdd进行分区。               这样可以很好地将数据分配到x no桶中,但我想不能保证每个桶只有1个密钥。

如果您使用Spark 1.6并使用数据框,则可以定义这样的udf val hasher = udf((i:Int)=>Hashing.consistentHash(Hashing.murmur3_32().newHasher().putInt(i) .hash.asInt(),PARTITION_SIZE))dataframe.repartition(hasher(keyThatYouAreUsing)) const SCALE_X = PixiStages.game._width * 0.0012; const SCALE_Y = PixiStages.game._height * 0.0018; this.scale.x = SCALE_X; this.scale.y = SCALE_Y * ( 0.5 + 0.5 * gamePiece.y / Game.TILE_ROWS ); const getStageXFromBoardX = ( board_x ) => { const tileWidth = SCALE_X * 38; return board_x*tileWidth; } const getStageYFromBoardY = ( board_y ) => { const tileHeight = SCALE_Y * 44; return board_y*tileHeight/4 + board_y*board_y*tileHeight / (8*Game.TILE_ROWS); }     希望这提供了一些启动的提示。

答案 1 :(得分:1)

我找到了Efficient UD(A)Fs with PySpark的解决方案 这个博客

  1. mapPartitions分割数据;
  2. udaf将spark数据帧转换为pandas dataframe;
  3. 在udaf中执行数据etl逻辑并返回pandas数据帧;
  4. udaf会将pandas数据帧转换为spark dataframe;
  5. toDF()合并结果spark数据帧并执行一些持久化操作,如SaveAsTable;
  6. python df = df.repartition('guestid').rdd.mapPartitions(udf_calc).toDF()