创建函数
功能描述
DLI支持创建使用UDF和UDTF等自定义函数应用于Spark作业开发当中。
具体使用自定义函数端到端的开发指导可以参考:Spark SQL作业使用UDF和Spark SQL作业使用UDTF。
语法格式
1 2 3 4 5 |
CREATE FUNCTION [db_name.]function_name AS class_name [USING resource,...] resource: : JAR file_uri |
或
1 2 3 4 5 |
CREATE OR REPLACE FUNCTION [db_name.]function_name AS class_name [USING resource,...] resource: : JAR file_uri |
注意事项
- 如果在数据库中存在同名的函数,系统将会报错。
- 只支持Hive语法创建函数。
- 请注意避免该场景:如果创建的自定义函数F1指定类C1,程序包名JAR1,创建自定义函数F2也指定类C1,程序包JAR2,因为F2和F1使用相同的类名,导致功能相互冲突,影响作业执行。
- 如需使用UDF热加载功能请提交工单开通白名单。
关键字
- USING <resources>:需要加载的资源。可以是JAR、文件或者URI的列表。
- OR REPLACE:支持自定义函数热加载功能。
- 如果创建自定义函数时不携带OR REPLACE,则需要注意以下场景:
表1 不携带OR REPLACE场景说明 序号
场景说明
场景举例
生效机制
操作影响
场景一
修改了原有程序包类的实现逻辑,重新创建的函数指定的JAR包名和类名保持和原有一致。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- 后续对J1包中函数实现做了逻辑修改,重新执行创建函数F2,指定类名C1,Jar包名J1。
说明:
注意,如果步骤2继续使用函数名F1,则会因为函数名重复导致创建失败。这时可以考虑使用OR REPLACE,或者替换所有作业中的函数F1为F2。
需要重启Spark SQL队列后新创建的自定义函数F2生效
- 需要重启Spark SQL队列,影响当前运行的作业。
- 重启队列后,影响F1原有功能,F1的功能变为和F2一样。
场景二
在原有程序包类的基础上新增了类,新创建的函数指定为新增的类,包名不变。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- J1的Jar包中新增了类C2,C1保持不变,新创建自定义函数F2,指定类名C2,Jar包名J1。
需要重启Spark SQL队列后新创建的自定义函数F2生效
- 需要重启Spark SQL队列,影响当前运行的作业。
- 重启队列后,F1的功能不变。
场景三
原有程序包类的实现逻辑不变,重新打包程序包名。新创建的函数指定新JAR包名,类名保持不变。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- 重新打包Jar包为J2,功能逻辑不变。新创建的自定义函数F2,指定类名C1,Jar包名J2。
新创建的自定义函数F2立即生效
无影响。
- 如果创建自定义函数携带OR REPLACE,表示需要对已有的函数内容进行功能替换并实时生效。
- 该功能开启当前需要提交工单开通白名单。
- 如果要在所有SQL队列上立即生效,需要分别选择SQL队列执行一遍:CREATE OR REPLACE xxx FUNCTION ...,否则没有执行的队列可能延迟0-12小时生效。
- 如果当前运行的作业中使用自定义函数F1,该F1函数指定类名C1,程序包名J1,作业运行了一半后,重新修改J1程序包逻辑,CREATE OR REPLACE FUNCTION F1后,后续作业使用新的F1函数逻辑,但是已执行完一半的作业使用旧的函数逻辑。
表2 携带OR REPLACE场景说明 序号
场景说明
场景举例
生效机制
操作影响
场景一
修改了原有程序包类的实现逻辑,重新创建的函数指定的JAR包名和类名保持和原有一致。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- 后续对J1包中函数实现做了逻辑修改,重新执行创建函数F1,指定类名C1,Jar包名J1。
立即生效
F1的功能变成新修改的逻辑。
场景二
在原有程序包类的基础上新增了类,新创建的函数指定为新增的类,包名不变。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- J1的Jar包中新增了类C2,C1保持不变,新创建自定义函数F2,指定类名C2,Jar包名J1。因为是第一次创建指定C2的函数,这时该F2函数不能立即生效。
两种生效方式
- CREATE OR REPLACE F2 FUNCTION创建语句再执行一次生效
- 重启Spark SQL队列后生效
如果是选择重启Spark SQL队列,则会导致当前运行的作业受影响。
场景三
修改了原有程序包类的类名,新创建的函数指定为新类名,包名不变。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- J1的Jar包中修改原C1为C2,C1已经不存在,新创建自定义函数F2,指定类名C2,Jar包名J1。
立即生效
F1功能失效,F2功能立即生效。
场景四
原有程序包类的实现逻辑不变,重新打包程序包名。新创建的函数指定新JAR包名,类名保持不变。
- 在Spark SQL队列下已创建自定义函数F1,指定类名C1,Jar包名J1。
- 重新打包Jar包为J2,功能逻辑不变。新创建的自定义函数F2,指定类名C1,Jar包名J2。
立即生效
无影响。
- 如果创建自定义函数时不携带OR REPLACE,则需要注意以下场景:
示例
创建函数mergeBill。
1 2 |
CREATE FUNCTION mergeBill AS 'com.xxx.hiveudf.MergeBill' using jar 'obs://onlyci-7/udf/MergeBill.jar'; |