append和overwrite的区别
append:在原有分区上面追加
overwrite:覆盖原有分区数据,在原有分区上全量刷新
// 创建分区表
spark.sql("CREATE TABLE my_partitioned_table (col1 INT, col2 STRING) PARTITIONED BY (partition_col STRING)")
// 对DataFrame进行分区转换
val partitionedDF = df.repartition($"partition_col")
// 将数据插入到分区表中
partitionedDF.write.mode("overwrite").insertInto("my_partitioned_table")
coalesce和repartition的区别:
1.是否改变分区:都改变分区数
coalesce是合并或减少分区数,不shuffle,但数据量过大,分区数过少会出现 OO,需合理
repartition是增加(提高并行度)或减少分区数,会shuffle
2.coalesce是在原有节点上进行分区的合并,不会跨节点的进行分区的操作,而repartition会。
3.coalesce可用于减少文件数的优化
引申:
减少文件数的优化方法:
1)coalesce
val coalescedDF = originalDF.coalesce(numPartitions)
2)repartition
val repartitionedDF = originalDF.repartition(numPartitions)
3)插入时指定分区以减少分区数
// 对DataFrame按照分区列进行分区
val partitionedDF = originalDF.repartition($"partition_col")
// 将数据写入文件系统时指定分区列
partitionedDF.write.partitionBy("partition_col").parquet("path/to/output")
Cache缓存级别
DataFrame和DataSet默认的缓存级别都是 Memory_And_DISK, RDD默认的是 MEMORY_ONLY
为了数据安全性,也可以Cache()缓存操作,以避免程序多次进行重复的计算。Spark 的缓存具有容错机制,如果一个缓存的 RDD 的某个分区丢失了,Spark 将按照原来的计算过程,自动重新计算并进行缓存。
val dataset = spark.read.parquet(file)
dataset.cache()
或者:dataset.persist()
//控制缓存级别
dataset.persist(StorageLevel.MEMORY_ONLY)
*缓存和释放缓存
缓存: dataFrame.cache() 或 sparkSession.catalog.cacheTable(“tableName”)
释放缓存:dataFrame.unpersist() 或 sparkSession.catalog.uncacheTable(“tableName”)
SparkSQL Shuffle的默认并行度:
1)spark.sql.shuffle.partitions 默认并行度是200 sparksql控制 shuffle操作并行度,如joins
2)spark.default.parallelism 默认并行度是当前集群最大可用核心数 spark全局参数 RDD中运行算子的并行度,如joins,reduceByKey
kyro序列化:
rdd默认的是java序列化,相比而言,kyro序列化尺寸更小,效率更高,需要设置
val spark = SparkSession.builder()
.appName("MyApp")
.config("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
.getOrCreate()
kryo 序列化比 java 序列化更快更紧凑,但 spark 默认的序列化是 java 序列化并不是 spark 序 列化,因为 spark 并不支持所有序列化类型,而且每次使用都必须进行注册。注册只针对于 RDD。在 DataFrames 和 DataSet 当中自动实现了 kryo 。
创建临时表和全局临时表
创建临时表
DataFrame.createTempView()
创建全局临时表
DataFrame.createOrReplaceGlobalTempView()
Broadcast join
先将小表全都查询出来聚合到driver端,然后分发到大表在集群中的各个executors,做本地join,避免shuffle网络IO。使用场景:大表join小表 只能广播小表
调优 -reduce缓存和shuffle缓存
spark.reducer.maxSizeInFilght 默认为48mb,此参数指定reduce任务可以拉取多少数据量,增加此参数,可减少reduce拉取数据的次数,从而优化shuffle,一般调大96mb。
spark.shuffle.file.buffer 是shuffle时控制输出文件的内存缓存区大小,增大此参数值可以减少落盘创建文件所带来的的磁盘IO和系统调用的次数,默认32kb,一般调大到64kb。
val spark = SparkSession.builder()
.appName("MyApp")
.config("spark.shuffle.file.buffer", "64k")
.getOrCreate()
Spark注册UDF
SparkSession.udf.register 方法进行注册
#1.自定义函数
#2.注册自定义函数
Spark.udf.register("函数名",函数)
#3.使用自定义函数
import org.apache.spark.sql.functions._
import org.apache.spark.sql.types._
// 创建一个SparkSession
val spark = SparkSession.builder()
.appName("UDFExample")
.getOrCreate()
// 定义一个自定义的UDF函数
val myUDF = udf((input: String) => input.toUpperCase())
// 注册UDF函数
spark.udf.register("myUDF", myUDF)
// 使用注册的UDF函数进行查询
val df = spark.range(5)
.select(col("id"), myUDF(col("id")).as("uppercase"))
// 显示结果
df.show()
Scala接口
在dataframe中使用
# 定义自定义函数
def add_one(col: Double) = {
col + 1
}
# 注册自定义函数
spark.udf.register("add_one", add_one _)
# 使用自定义函数
import org.apache.spark.sql.functions
dataframe.withColumn("a2", functions.callUDF("add_one", functions.col("a")))
在SparkSql使用
#自定义函数
def strLen(string s) ={
str.length()
}
#注册自定义函数
Spark.udf.register("strLen",strLen _)
#使用自定义函数
Spark.sql("select name ,strLen(name) from table ")