doc: add necessary spaces to the udf
This commit is contained in:
parent
a07adec754
commit
53771fbebf
|
@ -6,7 +6,7 @@ toc_max_heading_level: 4
|
||||||
|
|
||||||
## UDF 简介
|
## UDF 简介
|
||||||
|
|
||||||
在某些应用场景中,应用逻辑需要的查询功能无法直接使用TDengine内置的函数来实现。TDengine允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF在集群中注册成功后,可以像系统内置函数一样在SQL中调用,就使用角度而言没有任何区别。UDF分为标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值abs、正弦函数sin、字符串拼接函数concat等。聚合函数对多行数据输出一个值,如求平均数avg、取最大值max等。
|
在某些应用场景中,应用逻辑需要的查询功能无法直接使用 TDengine 内置的函数来实现。TDengine 允许编写用户自定义函数(UDF),以便解决特殊应用场景中的使用需求。UDF 在集群中注册成功后,可以像系统内置函数一样在 SQ L中调用,就使用角度而言没有任何区别。UDF 分为标量函数和聚合函数。标量函数对每行数据输出一个值,如求绝对值(abs)、正弦函数(sin)、字符串拼接函数(concat)等。聚合函数对多行数据输出一个值,如求平均数(avg)、取最大值(max)等。
|
||||||
|
|
||||||
TDengine 支持用 C 和 Python 两种编程语言编写 UDF。C 语言编写的 UDF 与内置函数的性能几乎相同,Python 语言编写的 UDF 可以利用丰富的 Python 运算库。为了避免 UDF 执行中发生异常影响数据库服务,TDengine 使用了进程分离技术,把 UDF 的执行放到另一个进程中完成,即使用户编写的 UDF 崩溃,也不会影响 TDengine 的正常运行。
|
TDengine 支持用 C 和 Python 两种编程语言编写 UDF。C 语言编写的 UDF 与内置函数的性能几乎相同,Python 语言编写的 UDF 可以利用丰富的 Python 运算库。为了避免 UDF 执行中发生异常影响数据库服务,TDengine 使用了进程分离技术,把 UDF 的执行放到另一个进程中完成,即使用户编写的 UDF 崩溃,也不会影响 TDengine 的正常运行。
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@ TDengine支持用C和Python两种编程语言编写UDF。C语言编写的UDF与
|
||||||
|
|
||||||
使用 C 语言实现 UDF 时,需要实现规定的接口函数
|
使用 C 语言实现 UDF 时,需要实现规定的接口函数
|
||||||
- 标量函数需要实现标量接口函数 scalarfn 。
|
- 标量函数需要实现标量接口函数 scalarfn 。
|
||||||
- 聚合函数需要实现聚合接口函数 aggfn_start , aggfn , aggfn_finish。
|
- 聚合函数需要实现聚合接口函数 aggfn_start、aggfn、aggfn_finish。
|
||||||
- 如果需要初始化,实现 udf_init;如果需要清理工作,实现 udf_destroy。
|
- 如果需要初始化,实现 udf_init;如果需要清理工作,实现 udf_destroy。
|
||||||
|
|
||||||
接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(`_start`, `_finish`, `_init`, `_destroy`)的连接。列表中的scalarfn,aggfn, udf需要替换成udf函数名。
|
接口函数的名称是 UDF 名称,或者是 UDF 名称和特定后缀(`_start`、`_finish`、`_init`、`_destroy`)的连接。
|
||||||
|
|
||||||
### 接口定义
|
### 接口定义
|
||||||
|
|
||||||
在TDengine中,UDF的接口函数名称可以是UDF名称,也可以是UDF名称和特定后缀(如_start、_finish、_init、_destroy)的连接。后面内容中描述的函数名称,例如scalarfn、aggfn,需要替换成UDF名称。。
|
在 TDengine 中,UDF 的接口函数名称可以是 UDF 名称,也可以是 UDF 名称和特定后缀(如_start、_finish、_init、_destroy)的连接。后面内容中描述的函数名称,例如 scalarfn、aggfn,需要替换成 UDF 名称。
|
||||||
|
|
||||||
#### 标量函数接口
|
#### 标量函数接口
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ int32_t scalarfn(SUdfDataBlock* inputDataBlock, SUdfColumn *resultColumn)
|
||||||
- 分组数据:相关数据会被分为多个行数据块(row data block),每个行数据块包含一组具有相同分组键(grouping key)的数据。
|
- 分组数据:相关数据会被分为多个行数据块(row data block),每个行数据块包含一组具有相同分组键(grouping key)的数据。
|
||||||
- 更新中间结果:对于每个数据块,调用 aggfn 函数更新中间结果。aggfn 函数会根据聚合函数的类型(如 sum、avg、count 等)对数据进行相应的计算,并将计算结
|
- 更新中间结果:对于每个数据块,调用 aggfn 函数更新中间结果。aggfn 函数会根据聚合函数的类型(如 sum、avg、count 等)对数据进行相应的计算,并将计算结
|
||||||
果存储在结果缓冲区中。
|
果存储在结果缓冲区中。
|
||||||
- 生成最终结果:在所有数据块的中间结果更新完成后,调用aggfn_finish函数从结果缓冲区中提取最终结果。最终结果通常只包含0条或1条数据,具体取决于聚
|
- 生成最终结果:在所有数据块的中间结果更新完成后,调用 aggfn_finish 函数从结果缓冲区中提取最终结果。最终结果只包含 0 条或 1 条数据,具体取决于聚
|
||||||
合函数的类型和输入数据。
|
合函数的类型和输入数据。
|
||||||
|
|
||||||
聚合函数的接口函数原型如下。
|
聚合函数的接口函数原型如下。
|
||||||
|
@ -52,7 +52,6 @@ int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *n
|
||||||
int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)
|
int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
其中 aggfn 是函数名的占位符。首先调用 aggfn_start 生成结果 buffer,然后相关的数据会被分为多个行数据块,对每个数据块调用 aggfn 用数据块更新中间结果,最后再调用 aggfn_finish 从中间结果产生最终结果,最终结果只能含 0 或 1 条结果数据。
|
其中 aggfn 是函数名的占位符。首先调用 aggfn_start 生成结果 buffer,然后相关的数据会被分为多个行数据块,对每个数据块调用 aggfn 用数据块更新中间结果,最后再调用 aggfn_finish 从中间结果产生最终结果,最终结果只能含 0 或 1 条结果数据。
|
||||||
|
|
||||||
主要参数说明如下。
|
主要参数说明如下。
|
||||||
|
@ -61,7 +60,6 @@ int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result)
|
||||||
- newInterBuf:新的中间结果缓冲区。
|
- newInterBuf:新的中间结果缓冲区。
|
||||||
- result:最终结果。
|
- result:最终结果。
|
||||||
|
|
||||||
|
|
||||||
#### 初始化和销毁接口
|
#### 初始化和销毁接口
|
||||||
|
|
||||||
初始化和销毁接口是标量函数和聚合函数共同使用的接口,相关 API 如下。
|
初始化和销毁接口是标量函数和聚合函数共同使用的接口,相关 API 如下。
|
||||||
|
@ -100,7 +98,7 @@ int32_t aggfn_start(SUdfInterBuf* interBuf) {
|
||||||
int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) {
|
int32_t aggfn(SUdfDataBlock* inputBlock, SUdfInterBuf *interBuf, SUdfInterBuf *newInterBuf) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
int32_t int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result) {
|
int32_t aggfn_finish(SUdfInterBuf* interBuf, SUdfInterBuf *result) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
int32_t aggfn_destroy() {
|
int32_t aggfn_destroy() {
|
||||||
|
@ -147,7 +145,7 @@ def process(input: datablock) -> tuple[output_type]:
|
||||||
```
|
```
|
||||||
|
|
||||||
主要参数说明如下:
|
主要参数说明如下:
|
||||||
- input:datablock 类似二维矩阵,通过成员方法 data(row,col)返回位于 row 行,col 列的 python 对象
|
- input:datablock 类似二维矩阵,通过成员方法 data(row, col) 读取位于 row 行、col 列的 python 对象
|
||||||
- 返回值是一个 Python 对象元组,每个元素类型为输出类型。
|
- 返回值是一个 Python 对象元组,每个元素类型为输出类型。
|
||||||
|
|
||||||
#### 聚合函数接口
|
#### 聚合函数接口
|
||||||
|
@ -163,7 +161,7 @@ def finish(buf: bytes) -> output_type:
|
||||||
|
|
||||||
首先,调用 start 函数生成最初的结果缓冲区。这个结果缓冲区用于存储聚合函数的内部状态,随着输入数据的处理而不断更新。
|
首先,调用 start 函数生成最初的结果缓冲区。这个结果缓冲区用于存储聚合函数的内部状态,随着输入数据的处理而不断更新。
|
||||||
|
|
||||||
然后,输入数据会被分为多个行数据块。对于每个行数据块,调用reduce函数,并将当前行数据块(inputs)和当前的中间结果(buf)作为参数传递。reduce函数会根据输入数据和当前状态来更新聚合函数的内部状态,并返回新的中间结果
|
然后,输入数据会被分为多个行数据块。对于每个行数据块,调用 reduce 函数,并将当前行数据块(inputs)和当前的中间结果(buf)作为参数传递。reduce 函数会根据输入数据和当前状态来更新聚合函数的内部状态,并返回新的中间结果。
|
||||||
|
|
||||||
最后,当所有行数据块都处理完毕后,调用 finish 函数。这个函数接收最终的中间结果(buf)作为参数,并从中生成最终的输出。由于聚合函数的特性,最终输出只能包含 0 条或 1 条数据。这个输出结果将作为聚合函数的计算结果返回给调用者。
|
最后,当所有行数据块都处理完毕后,调用 finish 函数。这个函数接收最终的中间结果(buf)作为参数,并从中生成最终的输出。由于聚合函数的特性,最终输出只能包含 0 条或 1 条数据。这个输出结果将作为聚合函数的计算结果返回给调用者。
|
||||||
|
|
||||||
|
@ -649,7 +647,6 @@ CREATE FUNCTION function_name AS library_path OUTPUTTYPE output_type LANGUAGE 'P
|
||||||
实现的 Python 文件路径。路径需要用英文单引号或英文双引号括起来。
|
实现的 Python 文件路径。路径需要用英文单引号或英文双引号括起来。
|
||||||
- output_type:函数计算结果的数据类型名称。
|
- output_type:函数计算结果的数据类型名称。
|
||||||
|
|
||||||
|
|
||||||
### 创建聚合函数
|
### 创建聚合函数
|
||||||
|
|
||||||
创建聚合函数的 SQL 语法如下。
|
创建聚合函数的 SQL 语法如下。
|
||||||
|
|
Loading…
Reference in New Issue