为什么要在spark的sql中使用自定义函数
当我们想要实现一些比较复杂运算逻辑的时候,我们一般需要自定义函数的帮助,比如假设我们现在有每个账号的人民币数额,我们需要展示出用户的美元数额的话,由于人民币和美元的汇率是变动的,一般都会做成一个http服务的的方式对外提供汇率关系,我们可以这么做:在自定义函数中通过调用外部的http汇率访问服务获取汇率信息,然后通过汇率和用户的人民币熟知进行运算,最终得到一个用户的美元数量,那么这种情况下自定义函数就可以帮我们大忙了
怎么实现spark sql的自定义函数
实现spark sql自定义函数的核心方法时spark.udf.register()方法,以下代码展示了如何完整实现一个spark sql自定义线性函数:
from pyspark import SparkConf
from pyspark.sql import SparkSession
import traceback
from pyspark.sql.types import IntegerType
appname = "test" # 任务名称
master = "local" # 单机模式设置
'''
local: 所有计算都运行在一个线程当中,没有任何并行计算,通常我们在本机执行一些测试代码,或者练手,就用这种模式。
local[K]: 指定使用几个线程来运行计算,比如local[4]就是运行4个worker线程。通常我们的cpu有几个core,就指定几个线程,最大化利用cpu的计算能力
local[*]: 这种模式直接帮你按照cpu最多cores来设置线程数了。
'''
# spark_driver_host = "10.0.0.248"
try:
# conf = SparkConf().setAppName(appname).setMaster(master).set("spark.driver.host", spark_driver_host) # 集群
conf = SparkConf().setAppName(appname).setMaster(master) # 本地
spark = SparkSession.builder.config(conf=conf).getOrCreate()
'''自定义函数--线性函数'''
def linearFunc(x):
return 10 * x + 5
'''注册函数到spark中'''
sqlLinear = spark.udf.register("linear", linearFunc, IntegerType())
sc = spark.sparkContext
player_source = [("kebo", 38), ("jordan", 46)]
rdd = sc.parallelize(player_source)
df = spark.createDataFrame(rdd, "name: string, age: int")
df.createOrReplaceTempView("player")
df2 = spark.sql("select name, linear(age) as funcResult from player")
df2.show()
spark.stop()
print('计算成功!')
except:
traceback.print_exc() # 返回出错信息
print('连接出错!')
程序运行的结果如下:
±-----±---------+
| name|funcResult|
±-----±---------+
| kebo| 385|
|jordan| 465|
±-----±---------+
可以看到我们实现了一个自定义的线性函数,该程序代码可以直接运行,其他的自定义函数的实现逻辑可以举一反三的实现