跳至主要内容

UDF 的可执行表函数

executable 表函数根据您在输出行到 stdout 的脚本中定义的用户定义函数 (UDF) 的输出创建表。可执行脚本存储在 users_scripts 目录中,并且可以读取来自任何来源的数据。确保您的 ClickHouse 服务器拥有运行可执行脚本所需的所有软件包。例如,如果它是一个 Python 脚本,请确保服务器已安装必要的 Python 软件包。

您可以选择包含一个或多个输入查询,这些查询将其结果流式传输到 stdin 供脚本读取。

注意

普通 UDF 函数与 executable 表函数和 Executable 表引擎之间的主要优势在于,普通 UDF 函数无法更改行数。例如,如果输入是 100 行,则结果必须返回 100 行。当使用 executable 表函数或 Executable 表引擎时,您的脚本可以进行任何您想要的数据转换,包括复杂的聚合。

语法

executable 表函数需要三个参数并接受可选的输入查询列表

executable(script_name, format, structure, [input_query...] [,SETTINGS ...])
  • script_name:脚本的文件名。保存在 user_scripts 文件夹中(user_scripts_path 设置的默认文件夹)
  • format:生成的表的格式
  • structure:生成的表的表架构
  • input_query:一个可选的查询(或查询集合),其结果通过 stdin 传递给脚本
注意

如果您要使用相同的输入查询重复调用同一脚本,请考虑使用 Executable 表引擎

以下 Python 脚本名为 generate_random.py,并保存在 user_scripts 文件夹中。它读取一个数字 i 并打印 i 个随机字符串,每个字符串前面都有一个用制表符分隔的数字

#!/usr/local/bin/python3.9

import sys
import string
import random

def main():

# Read input value
for number in sys.stdin:
i = int(number)

# Generate some random rows
for id in range(0, i):
letters = string.ascii_letters
random_string = ''.join(random.choices(letters ,k=10))
print(str(id) + '\t' + random_string + '\n', end='')

# Flush results to stdout
sys.stdout.flush()

if __name__ == "__main__":
main()

让我们调用脚本并让它生成 10 个随机字符串

SELECT * FROM executable('generate_random.py', TabSeparated, 'id UInt32, random String', (SELECT 10))

响应如下所示

┌─id─┬─random─────┐
│ 0 │ xheXXCiSkH │
│ 1 │ AqxvHAoTrl │
│ 2 │ JYvPCEbIkY │
│ 3 │ sWgnqJwGRm │
│ 4 │ fTZGrjcLon │
│ 5 │ ZQINGktPnd │
│ 6 │ YFSvGGoezb │
│ 7 │ QyMJJZOOia │
│ 8 │ NfiyDDhmcI │
│ 9 │ REJRdJpWrg │
└────┴────────────┘

设置

  • send_chunk_header - 控制是否在发送数据块以进行处理之前发送行数。默认值为 false
  • pool_size — 池的大小。如果将 0 指定为 pool_size,则没有池大小限制。默认值为 16
  • max_command_execution_time — 处理数据块的可执行脚本命令执行的最大时间。以秒为单位指定。默认值为 10。
  • command_termination_timeout — 可执行脚本应包含主读写循环。表函数销毁后,管道关闭,可执行文件将有 command_termination_timeout 秒的时间关闭,然后 ClickHouse 将向子进程发送 SIGTERM 信号。以秒为单位指定。默认值为 10。
  • command_read_timeout - 从命令 stdout 读取数据的超时时间(以毫秒为单位)。默认值为 10000。
  • command_write_timeout - 向命令 stdin 写入数据的超时时间(以毫秒为单位)。默认值为 10000。

将查询结果传递给脚本

请务必查看 如何将查询结果传递给脚本Executable 表引擎中的示例。以下是如何使用 executable 表函数在该示例中执行同一脚本

SELECT * FROM executable(
'sentiment.py',
TabSeparated,
'id UInt64, sentiment Float32',
(SELECT id, comment FROM hackernews WHERE id > 0 AND comment != '' LIMIT 20)
);