太久没写博客了,我,回来了。
忙完毕业,写点啥呢,写点实习中的东西吧,主要关于spark的使用相关,相当于之前spark-scala的进阶版?惯例,我主要是做个笔记自己看的,如有雷同,算我抄你的。
- rdd与dataframe选哪个用
- dataframe的几个操作
- 一些环境参数的配置与submit的问题
- 一些语法细节的坑
rdd与dataframe
先说重点:尽量使用dataframe
看下,谢谢作者。
- rdd
(1)遇到action算子触发作业,transformation算子是不会立即触发作业提交,具体细节百度/Google;
(2)stage的划分,划分的依据是依赖算子是否是shuffle(如reduceByKey,Join等)的,每个stage又可以划分成若干task;这个可以这么看,没有shuffle之前都是map操作,不怎么涉及节点之间的通信;
(3)分区(Partition),影响你的并发和计算效率,比如,1000个并发,200个Partition,另外800个并发就空闲着,所以合理的设置repartition和shuffle.partitions - dataframe
(1)DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格,和sql像的很;
(2)Spark SQL得以洞察更多的结构信息,从而对藏于DataFrame背后的数据源以及作用于DataFrame之上的变换进行了针对性的优化,最终达到大幅提升运行时效率的目标;RDD,由于无从得知所存数据元素的具体内部结构,Spark Core只能在stage层面进行简单、通用的流水线优化。
dataframe的几个操作
想起来几个算几个吧,有点忘了。。
- 一行变多行
explode[A, B](inputColumn: String, outputColumn: String)
例子1:xxDF.explode( “c3” , “c3_” ){time: String => time.split( ” ” )},原始c3列为String类型;
例子2:withColumn(“A_”, explode(col(“A”))).drop(“A”),原始A列为Array类型; - 多行变一行
groupBy(col1: String, cols: String*)
例子1:groupBy(“A”).agg(collect_list(“B”) as “B_list”).withColumn(“C”, func1(func2(col(“B_list”)))); - 多列拼接为一列
concat
例子1: select(col(“A”), concat(col(“B”), lit(“\t”), col(“C”)) as “BC”) - 一列变多列
withColumn也行 - join操作
大表放左边 - 填补缺失项
DF.na.fill(value = 1.0f, cols=Array(“A”)) - 增加某一固定列
withColumn(“flag”, lit(“666”)) - 重命名某一列
withColumnRenamed(“A”, “C”) - 转换列的数据类型
例子1:val df2 = df1.withColumn(“id1”,col(“id”).cast(StringType)).drop(“id”) - 比较diff
例子1:val diff = when(col(“id1”) === col(“id”),1).otherwise(0)
val cross_df = df2.join(df2_,”id”,”left”).withColumn(“diff”, diff).filter(col(“diff”) === 0) - dataframe某列进行统计排序
例子1:val df_count = df_label.select(“T”).groupBy(“T”).count
val df_count_sort = df_count.orderBy(“count”)
细节见//
一些参数上的配置与submit的问题
常见的就不说了,说下其他的,主要是优化任务执行:
- 预执行/推测任务
推测任务是指对于一个Stage里面拖后腿的Task,会在其他节点的Executor上再次启动这个task,如果其中一个Task实例运行成功则将这个最先完成的Task的计算结果作为最终结果,同时会干掉其他Executor上运行的实例。spark推测式执行默认是关闭的,可通过spark.speculation属性来开启。
换句话说:有的搬砖工实在搬这个task太累,那么启动其他并发来做这个,谁先做完就把其他的任务kill掉,很明显这样可以提高速度,但是需要额外的资源。需要观察任务执行的时间分布,如果存在明显拖后腿的现象,则可以使用 - GC Time
GC Time太长,影响任务的速度。集群硬件的配置此处不太懂,不乱说,从使用者的角度,GC Time过高解决的思路:
(1)给每个task分配的内存的确很少,调大内存executor memory
(2)机器负载太重,cpu占用过高,导致没有cpu资源进行gc,从而gc时间长。(可以加入sepculate机制)
其他submit参数优化见,谢谢作者。
一些语法细节的坑
- 读取文件
本地文件:sc.textFile(“file:///home/xx”);
hafs文件:spark.read.parquet(“hdfs://xx”)
注意本地的斜杠有3个; - trim函数
删除指定字符串的首尾空白符,类似会把什么”\001”,”\002”、”\t”、”\n”等都去掉的,小心用; - split函数
主要关于split不小心会丢掉后面的空字符串,有毒,细节见; - 一点小操作
如果需要简单的二次排序,将2个key组合为tuple作为key,然后sortBy;