记录一下 clickhouse的java udf 函数实现
主要参考了以下文章,找到的教程使用的是JSONEachRow格式传入数据,我使用的是 TabSeparated
注意!!!经过后来的 udf 使用实践,使用 TabSeparated 时,如果传入的数据中包含换行符时,会报错,这个时候还是改成 JSONEachRow 就好了。下面参考文章的第一个就是用的这个方式。
UDFs User Defined Functions | ClickHouse Docs
Server Settings | ClickHouse Docs
注,我的clickhouse是使用 curl https://clickhouse.com/ | sh 的方式下载,./clickhouse install 的方式安装的,目录是默认目录
一、找到配置文件的位置
打开 /etc/clickhouse-server/config.xml ,搜索 user_defined_executable_functions_config ,这个是 java udf 配置文件的存放位置,内容如下:
[root@master ~]# vim /etc/clickhouse-server/config.xml
………………………………………………
<!-- Configuration of user defined executable functions -->
<user_defined_executable_functions_config>*_function.*ml</user_defined_executable_functions_config>
看的出来,配置文件名需要以 _fucntion.*ml 的方式结尾,推测可以使用 xml 或者 yaml,我使用的是 xml。我在测试过成功创建了一个 test_function_001.xml ,失败了,读取不到这个function,改成 test_001_function.xml 就可以了
二、创建 udf 函数的配置文件
在这个目录下创建一个文件,我创建的是 test_function.xml。另外,这里面的 udf 函数名称是可以和
[root@master ~]# vim /etc/clickhouse-server/test_function.xml
------------------------分割线-------------------------------
<functions>
<function>
<type>executable_pool</type>
<pool_size>1</pool_size>
<!--udf函数名称-->
<name>test_xutao_function</name>
<!--返回值类型-->
<return_type>String</return_type>
<!--返回值名称,默认值为result-->
<!--当format为JSONEachRow时,取返回json中的result字段-->
<return_name>result</return_name>
<!--输入参数-->
<argument>
<type>String</type>
<name>argument_1</name>
</argument>
<argument>
<type>String</type>
<name>argument_2</name>
</argument>
<!--input和output的数据格式化方式-->
<format>TabSeparated</format>
<!--command运行方式,0为指定命令,1为默认方式-->
<execute_direct>0</execute_direct>
<!--command命令,最好带上根目录,避免出现函数不支持问题-->
<command>/usr/bin/java -cp /var/lib/clickhouse/user_scripts/clickhouse-udf-0.01.jar com.example.clickhouse.Udf</command>
</function>
</functions>
保存之后,需要给文件 clickhouse 的用户权限
[root@master ~]# cd /etc/clickhouse-server/
[root@master clickhouse-server]# chown -R clickhouse:clickhouse *
[root@master clickhouse-server]# ll
dr-x------. 2 clickhouse clickhouse 111 6月 20 10:00 config.d
-r--------. 1 clickhouse clickhouse 88191 6月 20 10:00 config.xml
-rw-r--r--. 1 clickhouse clickhouse 1443 6月 25 17:45 test_function.xml
dr-x------. 2 clickhouse clickhouse 34 6月 20 10:00 users.d
-r--------. 1 clickhouse clickhouse 5724 6月 20 10:00 users.xml
三、编写udf java 程序
编写一个jar包,这个clickhouse的的参数传入使用的方式是 system.in ,返回的方式是 system.out ,所有jar包里面只能有一个 system.out 语句,我试过打印一行日志,后来命令行只显示了日志,第二个 system.out 就没有显示。我测试程序是传入两个参数,实际上传入几个参数都行,并没有这方面的限制。注意,我的程序是创建了一个 com.example.clickhouse 的包,直接复制可能运行不了。
package com.example.clickhouse;
import java.util.Scanner;
public class Encrypt {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String line = sc.nextLine();
// 按制表符分割参数
String[] params = line.split("\t");
// 确保有两个参数
if (params.length < 2) {
// 参数不足时返回空字符串
System.out.println("error! check parameter");
continue;
}
// 获取两个参数
String param1 = params[0];
String param2 = params[1];
// 处理
String result = process(param1, param2);
// 输出结果
System.out.println(result);
}
}
public static String process(String nothing, String value) {
return value + "_change";
}
}
四、上传jar包
先 cd 到 /var/lib/clickhouse/user_scripts/ 目录下面,如果没有就创建一个,我也不知道别的目录可不可以,我看别的教程是放到这个目录。然后把jar包上传到这里,再给 755 权限(我没有试过用默认的权限,我顺手给改了,对权限有要求的可以自己试试),用户改成clickhouse。
上传之后可以简单手动验证一下clickhouse 的调用。使用 echo -e 的方式传入参数,参数之前用 \t 分隔。如下图
echo -e "Hello\tWorld" | java -cp ./:./clickhouse-udf-0.01.jar com.example.clickhouse.Encrypt
[root@master ~]# cd /var/lib/clickhouse/user_scripts/
[root@master user_scripts]# rz
-----------------这里上传了一个文件-----------------
[root@master user_scripts]# ll
[root@master user_scripts]# chown -R clickhouse:clickhouse *
[root@master user_scripts]# chmod 755 *
[root@master user_scripts]# -rwxr-xr-x. 1 clickhouse clickhouse 1355 6月 24 16:39 clickhouse-udf-0.01.jar
[root@master user_scripts]# echo -e "Hello\tWorld" | java -cp ./:./clickhouse-udf-0.01.jar com.example.clickhouse.Encrypt
World_change
五、打开clickhouse进行验证
首先刷新函数,SYSTEM RELOAD FUNCTIONS; 刷新函数之后使用 select 查询出自己编写的 udf 名称,如果没有是有问题的。如果能找到,直接执行就可以了
[root@master user_scripts]# clickhouse-client --host=10.1.1.11 --port=9000 --database=default --user=default --password=lianshi
ClickHouse client version 25.7.1.591 (official build).
Connecting to database default at 10.1.1.11:9000 as user default.
Connected to ClickHouse server version 25.7.1.
Warnings:
* Linux transparent hugepages are set to "always". Check /sys/kernel/mm/transparent_hugepage/enabled
master :) SYSTEM RELOAD FUNCTIONS;
SYSTEM RELOAD FUNCTIONS
Query id: 1d1536dc-bc55-481f-a927-c15a599b10d4
Ok.
0 rows in set. Elapsed: 0.007 sec.
master :) show functions like 'test_%'
Query id: b35a5bfd-7069-4043-aa90-48b10d0a1def
┌─name──────────────────────┬─is_aggregate─┬─case_insensitive─┬─alias_to─┬─create_query─┬─origin────────────────┬─description─┬─syntax─┬─arguments─┬─returned_value─┬─examples─┬─introduced_in─┬─categories─┐
1. │ test_xutao_function │ 0 │ 0 │ │ │ ExecutableUserDefined │ │ │ │ │ │ │ │
└───────────────────────────┴──────────────┴──────────────────┴──────────┴──────────────┴───────────────────────┴─────────────┴────────┴───────────┴────────────────┴──────────┴───────────────┴────────────┘
master :) select test_xutao_function('asd','saew');
SELECT test_xutao_function('asd', 'saew')
Query id: 7d22242f-5c47-4609-babb-cbdeaf9eefa5
┌─test_xutao_f⋯d', 'saew')─┐
1. │ saew_change │
└──────────────────────────┘
如上图,这个 udf 函数已经创建成功并且执行了,如果要处理clickhouse 列的数据,也可以。我创建了一个 test 表,表里面有一个 name 字段,是这么写的:
master :) select test_xutao_function('default.test.name',name) from test where name = 'bbbbbbbbbbbbbbbbbbb';
SELECT test_xutao_function('default.test.name', name)
FROM test
WHERE name = 'bbbbbbbbbbbbbbbbbbb'
Query id: 359cabea-2180-4db5-b86f-b333060bcec2
┌─test_xutao_fu⋯name', name)─┐
1. │ bbbbbbbbbbbbbbbbbbb_change │
└────────────────────────────┘
1 row in set. Elapsed: 0.100 sec.
master :)
更多推荐
所有评论(0)