函数管理
函数管理,是 离线开发 提供的专用于对SQL任务编辑时需要的系统函数和自定义函数进行管理的功能,在此页面可以进行新建目录、新建函数的操作。 函数管理模块下显示的全部函数,无论是系统默认的还是自定义函数,仅用于SQL类型的任务和脚本。 在「数据开发」模块,点击左侧的「函数管理」面板,根据当前项目的引擎不同,可查看函数信息,离线开发支持不同引擎下的系统函数查看,支持Hadoop引擎(Spark Thrift Server)下的自定义函数注册和Greenplum引擎的自定义定数和存储过程创建。
系统函数
系统函数是引擎本身所支持的函数,在「数据开发」模块中,点击左侧的「函数管理」面板,根据当前项目接入的引擎,会列出相应的函数信息,但离线开发列出的函数可能存在遗漏,不同引擎的函数请参考其官方文档
离线开发目前仅支持系统函数的查看,不支持新增、编辑、删除系统函数
SparkSQL UDF
创建步骤
用户自定义函数(User Defined Function,简称 UDF),是用户除了使用系统函数外,自行创建的函数,用于满足个性化的计算需求。自定义函数在使用上与普通的系统函数类似。 本文将通过字符处理函数,说明用户自定义函数的创建过程,以及如何在离线开发中使用该函数,具体流程图如下所示:
操作步骤:
- 在本地编写代码并编译为Jar包
在本地Java环境中按照Spark的UDF框架编写Java代码实现函数,本示例的代码如下所示:
import org.apache.hadoop.hive.ql.exec.UDF;
public class HelloUDF extends UDF{
public String evaluate(String str){
try{
return "helloWorld" + str;
}catch (Exception e){
return null;
}
}
}
JAVACopied!
将以上代码编译成Jar包。
目前仅支持Hadoop引擎下的自定义函数,且目前仅支持通过Spark Thrift Server进行函数的注册创建
- 上传资源到离线开发
在「数据开发」模块,点击左侧的「资源管理」面板并上传资源文件至任意目录
- 新建自定义函数并引用资源
进入「数据开发」模块,打开左侧的「函数管理」面板,右键选择「新建函数」,填写弹出框中的各配置项:
- 函数名称:填写函数名,例如sum、split等,在SQL中使用本函数的名称
- 类名:填写完整的类路径,例如com.udf.sales.HelloWorld
- 资源:在前一步上传至离线开发的Jar包
- 用途:本函数用途的描述,例如:按照正则表达式pat来分割字符串str
- 参数说明:本函数输入参数的说明,例如:按照正则表达式pat来分割字符串str,分割后以数组字符串的形式返回
- 选择存储位置:在左侧的树形结构中的存储位置
点击「确定」后,离线开发会通过Spark Thrift Server创建UDF,并根据用户输入的命令格式模拟调用,并在成功注册的通知信息中显示命令返回的结果
- 在SQL任务或脚本中使用函数
在离线开发的数据开发页面新建一个SQL任务,创建成功后在代码编辑器中编写SQL语句,如下所示:
select evaluate("A") from dual;
SQLCopied!
单击运行,即可查看结果。 此时,您已经完成自定义函数的创建和使用,并在SQL任务中看到使用效果
函数与资源的关系
函数与资源存在绑定关系,一个UDF需要绑定唯一的一个Jar包资源,但一个Jar包资源可以被不同的UDF多次引用
编辑/删除
在函数管理页面找到需要删除的函数,右键单击,在菜单栏选择「删除」,即可删除该函数。 目前不支持函数的编辑,也不支持函数的Jar包资源替换
特别注意
在进行UDF管理时,有以下内容需要特别注意:
- UDF是按项目划分的,不同项目可以创建同名的UDF,但是目前不支持跨项目引用UDF
- 受限于Spark Thrift Server的引擎特点,UDF不支持修改或Jar包资源替换
- 受限于Spark Thrift Server的引擎特点,UDF删除后,必须修改类名,才能创建同名UDF
SparkSQL UDF最佳实践
第一步:编写业务代码
例:输出简单的"hello world"
package com;
import org.apache.hadoop.hive.ql.exec.UDF;
public class Hello extends UDF {
public String evaluate(String name){
return "hello " + name;
}
}
JAVACopied!
Hello类必须继承hive的org.apache.hadoop.hive.ql.exec.UDF类,maven中依赖配置如下: | |
---|---|
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
<scope>provided</scope>
</dependency>
XMLCopied!
- 必须实现evaluate方法;
- evaluate方法必须是public修饰;
- evaluate返回值必须是具体的基本数据类型,比如int,string等;
第二步:打包业务代码
使用maven工具打包代码,maven打包配置示例:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
XMLCopied!
第三步:创建函数
- 上传jar包:在「数据开发-资源管理」上传jar包资源;
- 创建函数:在「数据开发-函数管理」新建函数,注意类名是类的全路径,比如:com.udf.Hello,函数名称和内置函数名不能重复;
新建函数时,类名必须是类的全路径,例如com.Hello
更多示例
传入数组作为函数参数
示例:
public String evaluate(String[] array)
{
return array[0];
}
JAVACopied!
参数列表定义为数组类型即可,在sql中只需按顺序将参数传入:
SELECT array_test("val1","val2",...) FROM dual;
如果还需要传入其它参数,则将其它参数至于数组参数之前:
public String evaluate(int n,String[] array)
{
return n + array[0];
}
JAVACopied!
sql中使用时第一个参数会匹配n,剩余的会作为数组传入。
在函数中读取文件
示例:
public String evaluate(String key)
{
BufferedReader jsonFile = null;
InputStreamReader ir = null;
try {
ir = new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("data.json"));
jsonFile = new BufferedReader(ir);
String lineString;
StringBuilder jsonStr = new StringBuilder();
while ((lineString = jsonFile.readLine()) != null) {
jsonStr.append(lineString);
}
JSONObject jsonObject = JSONObject.parseObject(jsonStr.toString());
return jsonObject.getString(key);
} catch (Exception e){
e.printStackTrace();
} finally {
try {
if (ir != null){
ir.close();
}
if(jsonFile != null){
jsonFile.close();
}
} catch (Exception e){
e.printStackTrace();
}
}
return "";
}
JAVACopied!
注意:可以将数据文件放在工程的package或者Resource目录下,打包时必须将依赖的其它包一起打包,比如这个例子中用到json解析的jar包:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
XMLCopied!
Greenplum UDF
与Spark SQL的UDF注册不同,Greenplum支持直接在离线开发上创建UDF。
在Greenplum的新建自定义函数弹窗中直接填写函数逻辑,创建成功后即可在任务中正常调用;
Greenplum 存储过程
创建与使用过程与Greenplum UDF一致;