Clickhouse 用户自定义外部函数

写在前面
Clickhouse 从 21.11 版本开始,除了提供类似SqlServer、MySQL CREATE FUNCTION 的自定义函数之外,还有一个用户自定义函数(UDF),与其说是“用户自定义函数”,为了避免混淆,称之为”用户自定义外部函数“更为准确。官方对此功能的解释:
ClickHouse can call any external executable program or script to process data.
译文:ClickHouse可以调用任何外部可执行程序或脚本来处理数据。
可以调用外部程序或脚本来处理数据,这对于数据建模、数据分析等等来说,无疑是杀手锏的存在。
开始
示例情景:调用python脚本实现向量点积运算。
环境:Docker、Clickhouse 21.11.4.14 、Ubuntu 20.04、Python3
1. 在config.xml里内增加
<user_defined_executable_functions_config>*_function.xml</user_defined_executable_functions_config>
2. 增加custom_function.xml自定义函数的声明文件
新建custom_function.xml文件,与config.xml、users.xml文件是同级目录下的,如图

3. 声明方法
打开custom_function.xml文件,编写文件内容如下:
<functions>
<function>
<type>executable</type>
<name>custom_dotProduct</name>
<return_type>Float32</return_type>
<return_name>result</return_name>
<argument>
<type>Array(Float32)</type>
<name>v1</name>
</argument>
<argument>
<type>Array(Float32)</type>
<name>v2</name>
</argument>
<format>JSONEachRow</format>
<execute_direct>0</execute_direct>
<command>python3 /var/lib/clickhouse/user_scripts/custom_dotProduct.py</command>
</function>
</functions>
execute_direct=0,默认是1,1表示将在clickhouse的/data/user_scripts文件夹内搜索脚本,0表是按照用户配置的命令搜索脚本路径,建议设置为0,避免找不到执行的脚本文件。其他参数可以参考文档:Introduction | ClickHouse Documentation
4. 编写python脚本
#!/usr/bin/python3
import sys
import json if __name__ == '__main__':
for line in sys.stdin:
dict = json.loads(line)
ls = []
for v in dict.values():
ls.insert(1, list(v))
vector1 = tuple(ls[0])
vector2 = tuple(ls[1])
v = sum(p * q for p, q in zip(vector1, vector2))
data = {'result': str(v)}
print(json.dumps(data), end='\n')
sys.stdout.flush()
保存脚本并命名为 custom_dotProduct.py ,再放到 /var/lib/clickhouse/user_scripts 文件夹内。
特别需要注意是脚本运行环境和存放路径问题,Clickhouse如果是放到docker里面,则需要在docker内配置python可运行的环境,其他C++、java也是如此,最起码能保证手动执行脚本的时候能运行。 在 custom_function.xml 声明方法的时候,编写的xml文件中的command命令是容器里面的路径,而不是宿主机的路径。
5. 至此已经完成,进行方法测试
--重新加载方法
SYSTEM RELOAD FUNCTIONS; --查看方法是否加载成功
SELECT * FROM system.functions WHERE name = 'custom_dotProduct';

执行方法:
select custom_dotProduct([1,2,3],[4,5,6]);

最后
还需特别注意的是Clickhouse版本问题,在示例的python脚本中和官网文档中的示例python脚本取值方法不太一样,
官方示例:
first_arg = int(value['argument_1'])
second_arg = int(value['argument_2'])
它是通过自定义配置的name获取值:
<function>
<type>executable</type>
<name>test_function_sum_json</name>
<return_type>UInt64</return_type>
<return_name>result_name</return_name>
<argument>
<type>UInt64</type>
<name>argument_1</name>
</argument>
<argument>
<type>UInt64</type>
<name>argument_2</name>
</argument>
<format>JSONEachRow</format>
<command>test_function_sum_json.py</command>
</function>
而我是通过遍历出来的:
for v in dict.values():
ls.insert(1, list(v))
原因是Clickhouse这种取值方式必须要求在 22.3 版本以上才支持,若低于 22.3的版本用官方的取值方式是永远报错的(巨坑之一)。具体可以看我之前提的Issue: UDFs: JSON Bug ? · Issue #35562 · ClickHouse/ClickHouse (github.com)
另外,从2022年1月后,Clickhouse的Docker镜像将停止 yandex/clickhouse-server 的迭代,使用新的镜像地址 clickhouse/clickhouse-server 。

如继续使用 yandex/clickhouse-server的镜像,最新的版本号停留在 22.1.3.7 (巨坑之二)。
好了,下班!不不不,等下下班!
Clickhouse 用户自定义外部函数的更多相关文章
- Jmeter外部函数引用
Jmeter外部函数引用 1.Beanshell引用Jmeter变量 添加用户自定义变量,输入变量名称和变量值,添加Debug sampler,用于输出初始变量值.
- 【C语言】外部函数和内部函数
目录 [外部函数] [内部函数] 1.外部函数 定义的函数能被本文件和其它文件访问(默认). 注:不允许有同名的外部函数. 2.内部函数 定义的函数只能被本文件访问,其它文件不能访问. 注:允许 ...
- 如何在 ejs 模板中使用 helper function 外部函数进行特殊处理?
一般我们想要在 ejs 模板中使用外部函数用于特殊的处理,比如:<%= ellipsis(title, 30) %> 通常的做法是: 使用 app.locals 来定义: app.loca ...
- pbfunc外部函数扩展应用-直接在Datawindow中生成QR二维码,非图片方式
利用pbfunc外部函数在Datawindow中直接生成QR二维码,非图片方式.需要注意以下面几点: Datawindow的DataObject的单位必须为像素(Pixels). Datawindow ...
- c语言,全局变量,局部变量,外部函数,内部函数,stasic和extern的复习总结
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...
- Spark SQL 用户自定义函数UDF、用户自定义聚合函数UDAF 教程(Java踩坑教学版)
在Spark中,也支持Hive中的自定义函数.自定义函数大致可以分为三种: UDF(User-Defined-Function),即最基本的自定义函数,类似to_char,to_date等 UDAF( ...
- 用static声明外部变量与内、外部函数
1.用static声明外部变量 若希望某些外部变量只限于被本文件引用,而不能被其他文件引用,可以在定义外部变量时加一个static声明. 例:(file1.c) #include <stdafx ...
- 外部函数/external
定义在moodle/lib/externallib.php 概观 外部函数API允许您创建可由外部程序(如Web服务API)访问的完全参数化的方法. 外部函数位于externallib.php文件中. ...
- JNI的又一替代者—使用JNR访问Java外部函数接口(jnr-ffi)
1. JNR简单介绍 继上文“JNI的替代者—使用JNA访问Java外部函数接口”,我们知道JNI越来越不受欢迎,JNI是编写Java本地方法以及将Java虚拟机嵌入本地应用程序的标准编程接口.它管理 ...
随机推荐
- C# typeof() 和object.GetType() 、Type..GetType()使用和区别
进行学习到表达树了,用动Tpye了.所以整理了以下他们区别和用法 总得来说他们都是为了获取某个实例具体引用的数据类型System.Type.1.GetType()方法继承自Object,所以C#中任何 ...
- Oracle表的约束
表的约束定义:表的约束是 ORACLE 数据库中应用在表数据上的一系列强制性规则 按照约束用途分类: PRIMARY KEY:主键约束 FOREIGN KEY:外键约束 CHECK:检查约束 UNIQ ...
- (第一章第二部分)TensorFlow框架之图与TensorBoard
系列博客链接: (一)TensorFlow框架介绍:https://www.cnblogs.com/kongweisi/p/11038395.html 本文概述: 说明图的基本使用 应用tf.Grap ...
- 前端人员不要只知道KFC,你应该了解 BFC、IFC、GFC 和 FFC
前言 说起KFC,大家都知道是肯德基,但面试官问你什么是BFC.IFC.GFC和FFC的时候,你是否能够像回答KFC是肯德基时的迅速,又或者说后面这些你根本就没听说过,作为一名前端开发工程师,以上这些 ...
- 矩池云上安装yolov5并测试教程
官方仓库:https://github.com/ultralytics/yolov5 官方文档:https://docs.ultralytics.com/quick-start/ 此案例我是租用了k8 ...
- C++雾中风景18:C++20, 从concept开始
转眼间,C++20的标准已经发布快两年了.不少C++的开源项目也已经将标准升级到最新的C++20了,笔者也开启了新标准的学习历程了.所以借这系列的博文,记录下笔者学习新标准的一些心得与吐槽~~ 作为C ...
- 【python】kNN基础算法--推荐系统
虽然把text转成全部量化是可以的,但是还是需要把text转成numpy的形式(这个是必须掌握的) 在将数据输入到分类器之前,必须将待处理数据的格式改变为分类器可以接受的格式. 数据规范化.数据归一化 ...
- 判断jQuery是否加载,如果未加载则加载
一般情况返回的js这么写history.go(-1) 但是如果是从别人分享过来的,就没有反应 所以就做个判断,没有上一页就返回首页 if (typeof jQuery == 'undefined') ...
- 从原理学习Java反序列化
1 序列化与反序列化 1.1 概念 序列化: 将数据结构或对象转换成二进制串的过程 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程 1.2 使用场景 当你想把的内存中的对象状态 ...
- kubernetes如何强制删除namespace
K8S如何强制删除namespace 先运行kubectl get namespace ingress-nginx -o json > nginx.json,拿到当前namespace描述,然后 ...