executable 테이블 함수

executable 테이블 함수 (executable)

stdout으로 행을 출력하는 스크립트로 정의한 사용자 정의 함수(UDF)의 출력을 기반으로 테이블을 만드는 테이블 함수예요. 실행 스크립트는 users_scripts 디렉터리에 저장되며 어떤 소스에서든 데이터를 읽을 수 있습니다. ClickHouse 서버에 실행 스크립트를 실행하는 데 필요한 모든 패키지가 있는지 확인하세요. 예를 들어 Python 스크립트라면 서버에 필요한 Python 패키지가 설치되어 있어야 합니다.

선택적으로 하나 이상의 입력 쿼리를 포함할 수 있는데, 이 쿼리 결과는 스크립트가 읽도록 stdin으로 스트리밍됩니다.

일반 UDF 함수와 executable 테이블 함수·Executable 테이블 엔진의 핵심 차이는, 일반 UDF 함수는 행 수를 바꿀 수 없다는 점입니다. 예를 들어 입력이 100행이면 결과도 반드시 100행을 반환해야 합니다. executable 테이블 함수나 Executable 테이블 엔진을 사용하면 복잡한 집계를 포함해 원하는 데이터 변형을 자유롭게 할 수 있어요.

출처: 문서

본문

executable 테이블 함수는 stdout으로 행을 출력하는 스크립트로 정의한 사용자 정의 함수(UDF)의 출력을 기반으로 테이블을 만듭니다. 실행 스크립트는 users_scripts 디렉터리에 저장되며 어떤 소스에서든 데이터를 읽을 수 있습니다. ClickHouse 서버에 실행 스크립트를 실행하는 데 필요한 모든 패키지가 있는지 확인하세요. 예를 들어 Python 스크립트라면 서버에 필요한 Python 패키지가 설치되어 있어야 합니다.

선택적으로 하나 이상의 입력 쿼리를 포함할 수 있는데, 이 쿼리 결과는 스크립트가 읽도록 stdin으로 스트리밍됩니다.

일반 UDF 함수와 executable 테이블 함수·Executable 테이블 엔진의 핵심 장점은, 일반 UDF 함수가 행 수를 바꿀 수 없는 반면 이 둘은 그렇지 않다는 점입니다. 예를 들어 입력이 100행이면 일반 UDF 결과는 반드시 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 — 풀 크기. pool_size0을 지정하면 풀 크기 제한이 없습니다. 기본값은 16.
  • max_command_execution_time — 데이터 블록 처리를 위한 최대 실행 스크립트 명령 실행 시간. 초 단위. 기본값은 10.
  • command_termination_timeout — 실행 스크립트는 메인 읽기-쓰기 루프를 포함해야 합니다. 테이블 함수가 파괴된 후 파이프가 닫히고, ClickHouse가 자식 프로세스에 SIGTERM 신호를 보내기 전에 실행 파일에 command_termination_timeout 초의 종료 시간이 주어집니다. 초 단위. 기본값은 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)
);

더 알아보기 (Learn more)