SparkSQL读取数据源
# A.给定读取数据源的类型和地址
spark.read.format("json").load(path)
spark.read.format("csv").load(path)
spark.read.format("parquet").load(path)
# B.直接调用对应数据源类型的方法
spark.read.json(path)
spark.read.csv(path)
spark.read.parquet(path)
# 特殊参数:option,用于指定读取或输出时的一些配置选项
# option("sep", "\t")指定分隔符
spark.read.format("csv").option("sep", "\t").load(path)
jdbcDF = spark.read \
.format("jdbc") \
.option("url", "jdbc:postgresql:dbserver") \
.option("dbtable", "schema.tablename") \
.option("user", "username") \
.option("password", "password") \
.load()
df.write \
.format("jdbc") \
.option("url", "jdbc:postgresql:dbserver") \
.option("dbtable", "schema.tablename") \
.option("user", "username") \
.option("password", "password") \
.save()
SparkSQL写出数据源
# a.给定输出数据源的类型和地址
df.write.format("json").save(path)
df.write.format("csv").save(path)
df.write.format("parquet").save(path)
# b.直接调用对应数据源类型的方法
df.write.json(path)
df.write.csv(path)
df.write.parquet(path)
# c.Save Mode
# 保存时指定怎么将数据写入目标数据源
df.write.mode(saveMode="append").format("csv").save(path)
# mode
append: 追加模式,当数据存在时,继续追加
overwrite: 覆写模式,当数据存在时,覆写以前数据,存储当前最新数据;
error/errorifexists: 如果目标存在就报错,默认的模式
ignore: 忽略,数据存在时不做任何操作
SparkSQL的UDF
# UDF,User Define Function,用户自定义函数
#1.定义一个普通的Python函数
#2.把Python函数注册到Spark中,注册方式有三种
(1)spark.udf.register(3个参数)
(2)F.udf(2个参数)
(3)@F.udf(1个参数)
案例
读写csv文件
# 读取
# 逗号分隔的文件
csv_df1 = spark.read.csv("../data/resources/people.txt")
csv_df1.printSchema()
csv_df1.show()
# 分号作为分隔的文件
csv_df2 = spark.read.format("csv").option("sep", ";").load("../data/resources/people.csv")
csv_df2.printSchema()
csv_df2.show()
# 制表符作为分隔符sep,以第一行的内容作为列名header,自动推断类型inferSchema
csv_df3 = spark.read.format("csv")\
.option("sep", "\t")\
.option("header", "true")\
.option("inferSchema", "true")\
.load("../data/resources/people.tsv")
csv_df3.printSchema()
csv_df3.show()
# 输出
csv_df1.write.csv("../data/output/csv/csv01")
csv_df2.write.format("csv").save(path="../data/output/csv/csv02")
csv_df3.write\
.mode("overwrite")\
.format("csv")\
.option("sep", "\t")\
.save(path="../data/output/csv/csv03")
读写json文件
# 读取
json_df1 = spark.read.json(path="../data/output/people.json")
json_df1.printSchema()
json_df1.show()
json_df2 = spark.read.format("json").load(path="../data/output/people.json")
json_df2.printSchema()
json_df2.show()
json_df3 = spark.read.format("json").option("path", "../datas/output/people.json").load()
json_df3.printSchema()
json_df3.show()
# 写出
json_df1.write.json(path="../data/output/json/json01")
json_df2.write.format("json").save(path="../data/output/json/json02")
json_df3.write\
.mode("overwrite")\
.format("json")\
.option("path", "../data/output/json/json03")\
.save()
UDF自定义函数
from pyspark.sql import SparkSession
import os
from pyspark.sql.types import StringType
import pyspark.sql.functions as F
# 1.构建SparkSession
# 建造者模式:类名.builder.配置…….getOrCreate()
# 自动帮你构建一个SparkConf对象,只要指定你需要哪些配置就可
spark = SparkSession \
.builder \
.master("local[2]") \
.appName("SparkSQLAppName") \
.config("spark.sql.shuffle.partitions", 4) \
.getOrCreate()
# 2.数据输入
input_df = spark.read.csv(path='../data/people.txt',
schema='name string, age int',sep=', ')
# 3.数据处理:把name字段后拼接一个"_itcast"
#自定义Python函数
#参数一:返回值类型
@F.udf(returnType=StringType())
def concat_name(name):
return name + "_itcast"
#register的三个参数:
#参数一:SQL中可以使用的自定义函数,只能在SQL用
#参数二:需要把那个Python函数注册到Spark中
#参数三:返回值类型,这是Java类型LongType(),IntegerType()
#concat_name_dsl1 = spark.udf.register(name="concat_name_sql",f=concat_name,
returnType=StringType())
#udf的两个参数:只能用于DSL
#参数一:自定义的Python函数
#参数二:返回值类型
#concat_name_dsl2 = F.udf(f=concat_name,returnType=StringType())
#3.1 SQL
input_df.createOrReplaceTempView("t1")
#result_df1 = spark.sql("select name,age,concat_name_sql(name) as concatName from t1")
#3.2 DSL
#result_df2 = input_df.select(input_df['name'],input_df['age'],
concat_name_dsl1(input_df['name']).alias('concatName_DSL1'))
#result_df3 = input_df.select(input_df['name'],input_df['age'],
concat_name_dsl2(input_df['name']).alias('concatName_DSL2'))
result_df4 = input_df.select(input_df['name'],input_df['age'],
concat_name(input_df['name']).alias('concatName_DSL3'))
# 4.数据输出
#input_df.printSchema()
#input_df.show()
#result_df1.show()
#result_df2.show()
#result_df3.show()
result_df4.show()
# 5.关闭SparkSession
spark.stop()
# PySpark的UDF实现
(1)注册方式一:spark.udf.register("sql中的函数",python自定义函数,返回值类型),
结果可以接收。接收后的结果可以在SQL或者DSL中使用。
(2)注册方式二:F.udf(Python自定义函数,返回值类型),结果可以接收,
接收后的结果只能在DSL中使用。
(3)注册方式三:在Python自定义函数上面,直接@F.udf(返回值类型),
本质上是Python装饰器。接收后的结果只能在DSL中,且函数名就是Python的函数名。
调优
SQL语句中的【group by】、【order by】,【distinct】关键字都会触发shuffle
触发shuffle的并行度参数【spark.sql.shuffle.partitions】,参数默认是【200】
可以适时降低,建议申请为CPU核数的2~3倍