ClickHouse自定义函数实例教程

ClickHouse v21.10 版本开始支持期待已久的特性————UDF(User defined function)。UDF通常通过SQL扩展数据库的能力,大多数采用SQL语句,但有些数据库还支持UDAF(user-defined aggregate function) 和UDTF(user defined table-generating function)。ClickHouse UDF通过lambda表达式定义,有参数、常量、操作符或其他函数调用组成。首先我们了解其语法,然后通过示例进行学习。

语法

CREATE FUNCTION name [ON CLUSTER cluster] AS (parameter0, ...) -> expression
  • 函数名称必须唯一,不能和系统函数冲突
  • 不支持递归调用
  • 所有函数使用的变量必须在参数列表中指定

简单示例:

CREATE FUNCTION linear_equation AS (x, k, b) -> k*x + b;
SELECT number, linear_equation(number, 2, 1) FROM numbers(3);

返回结果:

┌─number─┬─plus(multiply(2, number), 1)─┐
│      0 │                            1 │
│      1 │                            3 │
│      2 │                            5 │
└────────┴──────────────────────────────┘

上面示例来自官方文档,比较简单。下面的示例稍微复杂点,实用性更强。

实战案例

首先基于GenerateRandom Table Engine定义表,产生演示数据,后面自定义函数该表测试进行验证。

CREATE TABLE udf_rand
(
 `id` UInt32,
 `a` String,
 `b` String
) ENGINE = GenerateRandom(1, 15, 5);

定义表udf_rand,包括三个字段。随机表引擎的语法:

ENGINE = GenerateRandom([random_seed [,max_string_length [,max_array_length]]])

执行下面语句进行验证:


SELECT *
FROM udf_rand
LIMIT 10

Query id: 9b9139d7-c306-4f56-a071-54833370dd38

┌─────────id─┬─a───────────────┬─b──────────────┐
│ 4107652264 │ =@ep]Vw~        │ TlL#0FWJUeS}   │
│  652895061 │ b'zQI ,~6xGwg|  │                │
│ 2319105779 │ "M2e^ipx|,=a5N  │ 0Z3|ht_E8Ct    │
│ 1835960063 │                 │ A]BT&b!M-      │
│  730412674 │ 'l`*f{adU64F    │ Dj7peUH{TT2#sl │
│ 1014544494 │ '%Y~t99x]lB}    │ `K8P_@}a `kWg  │
│ 2554847195 │                 │ dof*O          │
│ 1382038526 │ wkDK            │ r;5qbK&t+      │
│  153951766 │ `xbguF(N3^n2?/; │ 4?a]2          │
│   85697048 │ 3&}|k3Igp@s=f,w │ _Kxs~%         │
└────────────┴─────────────────┴────────────────┘

下面基于uniq函数,定义两列唯一值数量之和的函数:

CREATE FUNCTION uniqTotal as (a, b) -> uniq(a) + uniq(b)

调用函数进行测试:


SELECT uniqTotal(a, b) AS total
FROM
(
    SELECT *
    FROM udf_rand
    LIMIT 10000
)

Query id: 5489d766-1b8c-42e7-9ded-acf11a125517

┌─total─┐
│ 17671 │
└───────┘

函数通过更简洁的方式实现了 SELECT uniq(x) + uniq(y)。下面再看一个示例,如何通过UDF简化复杂查询。

下面函数返回数组中最大元素,数据来自上面定义的测试表udf_rand,数据量有参数指定:

CREATE FUNCTION reduce_array_max AS size -> (
SELECT arrayReduce('max', grouped_ids)
FROM
(
SELECT arrayMap(x -> x, groupArray(id)) AS grouped_ids
FROM (SELECT id FROM udf_rand LIMIT size))
);

通过调用reduce_array_max函数,通过参数指定测试数据量。注意,函数定义包括了子查询,函数返回值也是子查询,因此select函数子句增加别名,否则返回列为:subquery1。


SELECT reduce_array_max(10000) AS reduced

Query id: fe927d4c-4431-4269-a3f8-13ff1eb1923b

┌────reduced─┐
│ 4294530630 │
└────────────┘

总结

定义UDF有下列优势:

  • 通过函数封装复杂代码,可以在多个应用场景中复用
  • 通过给定输入参数,可以简化测试
  • 修改函数定义自动反应至所有函数调用,避免重复维护

UDF可以消除重复工作,虽然强大,也不要过度滥用。

猜你喜欢

转载自blog.csdn.net/neweastsun/article/details/130235194