主要参考了以下文章,找到的教程使用的是JSONEachRow格式传入数据,我使用的是 TabSeparated        
注意!!!经过后来的 udf 使用实践,使用 TabSeparated 时,如果传入的数据中包含换行符时,会报错,这个时候还是改成 JSONEachRow 就好了。下面参考文章的第一个就是用的这个方式。

ClickHouse UDF 实践

ClickHouse UDF 实践_ITPUB博客

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 :) 

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐