Apache SPARK GroupByKey替代

时间:2014-12-10 13:34:39

标签: scala apache-spark

我的表格下面有列[col1,col2,key1,col3,txn_id,dw_last_updated]。在这些txn_id中,key1是主键列。在我的数据集中,我可以有多个(txn_id,key)组合的记录。在这些记录中,我需要根据dw_last_updated ..

选择最新的记录

我正在使用这个逻辑。我总是遇到内存问题而且我认为部分原因是因为groupByKey()...有没有更好的替代品呢?

case class Fact(col1: Int,
  col2: Int,
  key1: String,
  col3: Int,
  txn_id: Double,
  dw_last_updated: Long)

sc.textFile(s3path).map { row =>
          val parts = row.split("\t")
          Fact(parts(0).toInt,
            parts(1).toInt,
            parts(2),
            parts(3).toInt,
            parts(4).toDouble,
            parts(5).toLong)
        }).map { t => ((t.txn_id, t.key1), t) }.groupByKey(512).map {
          case ((txn_id, key1), sequence) =>
            val newrecord = sequence.maxBy {
              case Fact_Cp(col1, col2, key1, col3, txn_id, dw_last_updated) => dw_last_updated.toLong
            }
           (newrecord.col1 + "\t" + newrecord.col2 + "\t" + newrecord.key1 +
              "\t" + newrecord.col3 + "\t" + newrecord.txn_id + "\t" + newrecord.dw_last_updated)
        }

感谢您的想法/建议......

1 个答案:

答案 0 :(得分:1)

rdd.groupByKey收集每个键的所有值,需要必要的内存来保存单个节点上键的值序列。不鼓励使用它。请参阅[1]

鉴于我们只对每个键只有1个值感兴趣:max(dw_last_updated),更有效的内存方式是使用rdd.reduceByKey,其中reduce函数用于获取两个记录的最大值使用该时间戳作为判别式的相同密钥。

rdd.reduceByKey{case (record1,record2) => max(record1, record2)}

适用于您的情况,它应如下所示:

case class Fact(...)
object Fact {
  def parse(s:String):Fact = ???
  def maxByTs(f1:Fact, f2:Fact):Fact = if (f1.dw_last_updated.toLong > f2.dw_last_updated.toLong) f1 else f2
}
val factById = sc.textFile(s3path).map{row => val fact = Fact.parse(row); ((fact.txn_id, fact.key1),fact)}
val maxFactById = factById.reduceByKey(Fact.maxByTs)

请注意,我已在Fact配套对象上定义了实用程序操作,以保持代码整洁。我还建议给每个转换步骤或逻辑步骤组赋予命名变量。它使程序更具可读性。