我在spark中编写了一些代码如下:
val df = sqlContext.read.json("s3n://blah/blah.gz").repartition(200)
val newdf = df.select("KUID", "XFF", "TS","UA").groupBy("KUID", "XFF","UA").agg(max(df("TS")) as "TS" ).filter(!(df("UA")===""))
val dfUdf = udf((z: String) => {
val parser: UserAgentStringParser = UADetectorServiceFactory.getResourceModuleParser();
val readableua = parser.parse(z)
Array(readableua.getName,readableua.getOperatingSystem.getName,readableua.getDeviceCategory.getName)
})
val df1 = newdf.withColumn("useragent", dfUdf(col("UA"))) ---PROBLEM LINE 1
val df2= df1.map {
case org.apache.spark.sql.Row(col1:String,col2:String,col3:String,col4:String, col5: scala.collection.mutable.WrappedArray[String]) => (col1,col2,col3,col4, col5(0), col5(1), col5(2))
}.toDF("KUID", "XFF","UA","TS","browser", "os", "device")
val dataset =df2.dropDuplicates(Seq("KUID")).drop("UA")
val mobile = dataset.filter(dataset("device")=== "Smartphone" || dataset("device") === "Tablet" ).
mobile.write.format("com.databricks.spark.csv").save("s3n://blah/blah.csv")
以下是输入数据的示例 {“TS”:“1461762084”,“XFF”:“85.255.235.31”,“IP”:“10.75.137.217”,“KUID”:“JilBNVgx”,“UA”:“Flixster / 1066 CFNetwork / 758.3.15达尔文/ 15.4.0“}
所以在上面的代码片段中,我正在读取一个2.4GB大小的gz文件。读取时间为9分钟。按ID分组并取最大时间戳。但是(在问题第1行),添加列(带列)的行需要2个小时。此行需要用户代理并尝试派生操作系统,设备,Broswer信息。这是在这里做事的错误方式。
我在具有r3.4xlarge(8核和122Gb内存)的4节点AWS群集上运行此操作,具有以下配置
--executor-memory 30G --num-executors 9 --executor-cores 5
答案 0 :(得分:0)
这里的问题是gzip
不可拆分,无法并行读取。后台发生的情况是,单个进程将从存储桶中下载文件,然后将对其进行重新分区以在群集中分发数据。请将输入数据重新编码为a splittable format。如果输入文件没有太大变化,您可以考虑bzip2
(因为编码非常昂贵并且可能需要一些时间)。
答案 1 :(得分:0)
更新:从罗伯托那里获取答案,并将其贴在这里,以造福所有
您正在为UDF中的每一行创建一个新的解析器:val解析器:UserAgentStringParser = UADetectorServiceFactory.getResourceModuleParser(); 。构造它可能很昂贵,你应该在UDF之外构造一个并将其用作闭包