Spark / Scala:解析多行记录

时间:2016-02-29 07:43:22

标签: apache-spark

解析多行日志文件条目的正确spark | scala技术是什么? SQL跟踪文本文件:

# createStatement call (thread 132053, con-id 422996) at 2015-07-24 12:39:47.076339
# con info [con-id 422996, tx-id 47, cl-pid 50593, cl-ip 10.32.50.24, user: SAPABA, schema: SAPABA]
cursor_140481797152768_c22996 = con_c22996.cursor()

# begin PreparedStatement_execute (thread 132053, con-id 422996) at 2015-07-24 12:39:47.076422
# con info [con-id 422996, tx-id 47, cl-pid 50593, cl-ip 10.32.50.24, user: SAPABA, schema: SAPABA]
cursor_140481797152768_c22996.execute("SELECT DISTINCT  blah blah blah")
# end PreparedStatement_execute (thread 132053, con-id 422996) at 2015-07-24 12:39:47.077706

每条记录由三行组成;每种记录类型的属性(例如createStatementPreparedStatement)都不同。 我想逐行读取文件,确定记录类型,然后为每条记录创建一个数据帧行:

示例

insert into prepared_statements values (132053,422996, '2015-07-24 12:39:47.076422','SELECT DISTINCT  blah blah blah')

为了实现这一点,我需要检查每一行以确定它是哪种记录类型,然后读取接下来的两行以获取该记录类型的属性。另外,行格式根据记录的不同而不同,所以我需要有条件地检查每行三行的开始,以确定记录类型。是否有解析多行记录的火花技术?

1 个答案:

答案 0 :(得分:3)

这是一个有效的解决方案,基于将每一行与下一个空行的索引进行匹配,然后按这些索引进行分组,将每个“逻辑记录”的行组合在一起。 假设输入在rdd

val indexedRows: RDD[(String, Long)] = rdd.zipWithIndex().cache()
val emptyRowIndices = indexedRows.filter(_._1.isEmpty).values.collect().sorted

val withIndexOfNextGap: RDD[(String, Long)] = indexedRows
  .filter(!_._1.isEmpty)
  .mapValues(i => emptyRowIndices.find(_ > i).getOrElse(0)) // finds lowest index of empty line greater than current line index

val logicalRecords: RDD[Iterable[String]] = withIndexOfNextGap.map(_.swap).groupByKey().values

logicalRecords.map(f) // f maps each Iterable[String] into whatever you need

请注意,此解决方案有一些注意事项:

  • 假设“逻辑记录”(多行条目)的数量不太大,无法将索引收集到驱动程序内存
  • 由于我们将每行扫描这些索引,因此效率不高