메인 콘텐츠로 건너뛰기

사전 준비 사항

이 문서의 예시를 따라 하려면 다음이 필요합니다:
  • 실행 중인 ClickHouse 서버 인스턴스
  • curl이 설치되어 있어야 합니다. Ubuntu 또는 Debian에서는 sudo apt install curl을 실행하거나, 설치 방법은 이 문서를 참조하십시오.

개요

HTTP 인터페이스를 사용하면 모든 플랫폼에서 모든 프로그래밍 언어를 통해 REST API 형태로 ClickHouse를 사용할 수 있습니다. HTTP 인터페이스는 네이티브 인터페이스보다 제약이 더 많지만, 더 다양한 언어를 지원합니다. 기본적으로 clickhouse-server는 다음 포트에서 수신 대기합니다:
  • HTTP용 포트 8123
  • HTTPS를 활성화하면 포트 8443
매개변수 없이 GET / 요청을 보내면 문자열 “Ok.”와 함께 200 응답 코드가 반환됩니다:
$ curl 'http://localhost:8123/'
Ok.
“Ok.”는 http_server_default_response에 정의된 기본값으로, 필요에 따라 변경할 수 있습니다. 참고: HTTP 응답 코드 주의사항.

웹 사용자 인터페이스

ClickHouse에는 웹 사용자 인터페이스가 포함되어 있으며, 다음 주소에서 접속할 수 있습니다:
http://localhost:8123/play
웹 UI는 쿼리 실행 중 진행 상황 표시, 쿼리 취소, 결과 스트리밍을 지원합니다. 또한 쿼리 파이프라인의 차트와 그래프를 표시하는 숨겨진 기능도 제공합니다. 쿼리가 성공적으로 실행되면 다운로드 버튼이 나타나며, 이를 통해 쿼리 결과를 CSV, TSV, JSON, JSONLines, Parquet, Markdown 또는 ClickHouse가 지원하는 사용자 지정 포맷 등 다양한 포맷으로 다운로드할 수 있습니다. 다운로드 기능은 쿼리 캐시를 사용해 쿼리를 다시 실행하지 않고도 결과를 효율적으로 가져옵니다. UI에 여러 페이지 중 한 페이지만 표시되었더라도 전체 결과를 다운로드합니다. 웹 UI는 전문가를 위해 설계되었습니다. 상태 점검 스크립트에서는 GET /ping 요청을 사용하십시오. 이 핸들러는 항상 “Ok.”를 반환합니다(끝에 개행 문자가 포함됨). 버전 18.12.13부터 사용할 수 있습니다. 레플리카 지연을 확인하려면 /replicas_status도 참조하십시오.
$ curl 'http://localhost:8123/ping'
Ok.
$ curl 'http://localhost:8123/replicas_status'
Ok.

HTTP/HTTPS를 통한 쿼리

HTTP/HTTPS를 통해 쿼리하는 방법은 3가지입니다.
  • 요청을 URL의 ‘query’ 매개변수로 전송
  • POST 메서드 사용
  • 쿼리의 앞부분은 ‘query’ 매개변수로 보내고, 나머지는 POST로 전송
URL 크기는 기본적으로 1 MiB로 제한되며, http_max_uri_size 설정으로 변경할 수 있습니다.
성공하면 응답 코드 200과 함께 응답 본문에 결과가 반환됩니다. 오류가 발생하면 응답 코드 500과 함께 응답 본문에 오류 설명 텍스트가 반환됩니다. GET을 사용하는 요청은 ‘읽기 전용’입니다. 즉, 데이터를 수정하는 쿼리에는 POST 메서드만 사용할 수 있습니다. 쿼리 자체는 POST 본문이나 URL 매개변수로 보낼 수 있습니다. 몇 가지 예시를 살펴보겠습니다. 아래 예시에서는 curl을 사용해 SELECT 1 쿼리를 전송합니다. 공백에 URL 인코딩 %20을 사용한 점에 유의하십시오.
command
curl 'http://localhost:8123/?query=SELECT%201'
Response
1
이 예시에서는 wget에 -nv(간략 출력) 및 -O- 매개변수를 사용해 결과를 터미널에 출력합니다. 이 경우 공백은 URL 인코딩할 필요가 없습니다:
command
wget -nv -O- 'http://localhost:8123/?query=SELECT 1'
1
이 예시에서는 원시 HTTP 요청을 netcat으로 파이프합니다:
command
echo -ne 'GET /?query=SELECT%201 HTTP/1.0\r\n\r\n' | nc localhost 8123
response
HTTP/1.0 200 OK
X-ClickHouse-Summary: {"read_rows":"1","read_bytes":"1","written_rows":"0","written_bytes":"0","total_rows_to_read":"1","result_rows":"0","result_bytes":"0","elapsed_ns":"4505959","memory_usage":"1111711"}
Date: Tue, 11 Nov 2025 18:16:01 GMT
Connection: Close
Content-Type: text/tab-separated-values; charset=UTF-8
Access-Control-Expose-Headers: X-ClickHouse-Query-Id,X-ClickHouse-Summary,X-ClickHouse-Server-Display-Name,X-ClickHouse-Format,X-ClickHouse-Timezone,X-ClickHouse-Exception-Code,X-ClickHouse-Exception-Tag
X-ClickHouse-Server-Display-Name: MacBook-Pro.local
X-ClickHouse-Query-Id: ec0d8ec6-efc4-4e1d-a14f-b748e01f5294
X-ClickHouse-Format: TabSeparated
X-ClickHouse-Timezone: Europe/London
X-ClickHouse-Exception-Tag: dngjzjnxkvlwkeua

1
보시다시피 curl 명령은 공백을 URL 인코딩해야 하므로 다소 불편합니다. wget는 모든 항목을 자체적으로 이스케이프하지만, keep-alive와 Transfer-Encoding: chunked를 사용할 때 HTTP 1.1에서 제대로 작동하지 않으므로 사용을 권장하지 않습니다.
$ echo 'SELECT 1' | curl 'http://localhost:8123/' --data-binary @-
1

$ echo 'SELECT 1' | curl 'http://localhost:8123/?query=' --data-binary @-
1

$ echo '1' | curl 'http://localhost:8123/?query=SELECT' --data-binary @-
1
쿼리의 일부를 매개변수로 보내고 나머지를 POST로 보내면, 이 두 부분 사이에 개행 문자가 삽입됩니다. 예를 들어, 다음은 작동하지 않습니다:
$ echo 'ECT 1' | curl 'http://localhost:8123/?query=SEL' --data-binary @-
Code: 59, e.displayText() = DB::Exception: Syntax error: failed at position 0: SEL
ECT 1
, expected One of: SHOW TABLES, SHOW DATABASES, SELECT, INSERT, CREATE, ATTACH, RENAME, DROP, DETACH, USE, SET, OPTIMIZE., e.what() = DB::Exception
기본적으로 데이터는 TabSeparated 포맷으로 반환됩니다. 다른 포맷을 요청하려면 쿼리에서 FORMAT 절을 사용합니다. 예를 들면 다음과 같습니다:
command
wget -nv -O- 'http://localhost:8123/?query=SELECT 1, 2, 3 FORMAT JSON'
Response
{
    "meta":
    [
        {
            "name": "1",
            "type": "UInt8"
        },
        {
            "name": "2",
            "type": "UInt8"
        },
        {
            "name": "3",
            "type": "UInt8"
        }
    ],

    "data":
    [
        {
            "1": 1,
            "2": 2,
            "3": 3
        }
    ],

    "rows": 1,

    "statistics":
    {
        "elapsed": 0.000515,
        "rows_read": 1,
        "bytes_read": 1
    }
}
default_format URL 매개변수 또는 X-ClickHouse-Format 헤더를 사용하면 TabSeparated 이외의 포맷을 기본값으로 지정할 수 있습니다.
$ echo 'SELECT 1 FORMAT Pretty' | curl 'http://localhost:8123/?' --data-binary @-
┏━━━┓
 1
┡━━━┩
 1
└───┘
매개변수화된 쿼리에는 POST 메서드를 사용할 수 있습니다. 매개변수는 {name:Type}와 같이 중괄호 안에 매개변수 이름과 유형을 지정하는 방식으로 표현합니다. 매개변수 값은 param_name으로 전달합니다.
$ curl -X POST -F 'query=select {p1:UInt8} + {p2:UInt8}' -F "param_p1=3" -F "param_p2=4" 'http://localhost:8123/'

7

HTTP/HTTPS를 통한 삽입 쿼리

데이터를 전송할 때 INSERT 쿼리에는 POST 메서드가 필요합니다. 이 경우 쿼리의 앞부분은 URL 매개변수에 작성하고, 삽입할 데이터는 POST로 전달할 수 있습니다. 삽입할 데이터는 예를 들어 MySQL의 탭 구분 덤프일 수 있습니다. 이렇게 하면 INSERT 쿼리가 MySQL의 LOAD DATA LOCAL INFILE를 대체합니다.

예시

테이블(table)을 생성하려면:
$ echo 'CREATE TABLE t (a UInt8) ENGINE = Memory' | curl 'http://localhost:8123/' --data-binary @-
잘 알려진 INSERT 쿼리를 사용해 데이터를 삽입하려면:
$ echo 'INSERT INTO t VALUES (1),(2),(3)' | curl 'http://localhost:8123/' --data-binary @-
쿼리와 별도로 데이터를 전송하려면:
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
어떤 데이터 포맷이든 지정할 수 있습니다. 예를 들어, INSERT INTO t VALUES를 작성할 때와 동일한 ‘Values’ 포맷을 지정할 수 있습니다:
$ echo '(7),(8),(9)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20Values' --data-binary @-
탭으로 구분된 덤프에서 데이터를 삽입하려면 해당 포맷을 지정하십시오:
$ echo -ne '10\n11\n12\n' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20FORMAT%20TabSeparated' --data-binary @-
테이블 내용을 조회하려면:
$ curl 'http://localhost:8123/?query=SELECT%20a%20FROM%20t'
7
8
9
10
11
12
1
2
3
4
5
6
병렬 쿼리 처리로 인해 데이터가 무작위 순서로 출력됩니다
테이블을 삭제하려면:
$ echo 'DROP TABLE t' | curl 'http://localhost:8123/' --data-binary @-
데이터 테이블을 반환하지 않는 요청이 성공한 경우, 빈 응답 본문이 반환됩니다.

압축

대량의 데이터를 전송할 때 네트워크 트래픽을 줄이거나, 생성과 동시에 압축되는 덤프를 만들기 위해 압축을 사용할 수 있습니다. 데이터를 전송할 때 ClickHouse 내부 압축 포맷을 사용할 수 있습니다. 압축된 데이터는 비표준 포맷이므로, 이를 처리하려면 clickhouse-compressor 프로그램이 필요합니다. 이 프로그램은 clickhouse-client 패키지와 함께 기본적으로 설치됩니다. 데이터 삽입 효율을 높이려면 http_native_compression_disable_checksumming_on_decompress 설정을 사용하여 서버 측 체크섬 검증을 비활성화하십시오. URL에 compress=1을 지정하면 서버가 전송하는 데이터를 압축합니다. URL에 decompress=1을 지정하면 서버는 POST 메서드로 전달된 데이터의 압축을 해제합니다. HTTP 압축을 사용할 수도 있습니다. ClickHouse는 다음 압축 메서드를 지원합니다.
  • gzip
  • br
  • deflate
  • xz
  • zstd
  • lz4
  • bz2
  • snappy
압축된 POST 요청을 보내려면 요청 헤더에 Content-Encoding: compression_method를 추가하십시오. ClickHouse가 응답을 압축하도록 하려면 요청에 Accept-Encoding: compression_method 헤더를 추가하십시오. 모든 압축 메서드에 대해 http_zlib_compression_level 설정을 사용하여 데이터 압축 수준을 구성할 수 있습니다.
일부 HTTP 클라이언트는 기본적으로 서버가 보낸 데이터(gzipdeflate)의 압축을 해제할 수 있으므로, 압축 설정을 올바르게 사용하더라도 압축 해제된 데이터를 받게 될 수 있습니다.

예시

압축된 데이터를 서버로 전송하려면:
echo "SELECT 1" | gzip -c | \
curl -sS --data-binary @- -H 'Content-Encoding: gzip' 'http://localhost:8123/'
서버에서 압축된 데이터 아카이브를 받으려면:
curl -vsS "http://localhost:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' --output result.gz -d 'SELECT number FROM system.numbers LIMIT 3'

zcat result.gz
0
1
2
서버에서 압축된 데이터를 수신하고 gunzip으로 압축 해제된 데이터를 받으려면:
curl -sS "http://localhost:8123/?enable_http_compression=1" \
-H 'Accept-Encoding: gzip' -d 'SELECT number FROM system.numbers LIMIT 3' | gunzip -
0
1
2

기본 데이터베이스

database URL 매개변수 또는 X-ClickHouse-Database 헤더를 사용해 기본 데이터베이스를 지정할 수 있습니다.
echo 'SELECT number FROM numbers LIMIT 10' | curl 'http://localhost:8123/?database=system' --data-binary @-
0
1
2
3
4
5
6
7
8
9
기본적으로 서버 설정에 등록된 데이터베이스가 기본 데이터베이스로 사용됩니다. 별도의 설정이 없으면 default라는 이름의 데이터베이스가 사용됩니다. 또는 테이블 이름 앞에 점을 사용해 데이터베이스를 언제든지 지정할 수 있습니다.

인증

사용자 이름과 비밀번호는 다음 3가지 방법 중 하나로 지정할 수 있습니다.
  1. HTTP 기본 인증을 사용하는 방법입니다.
예시:
echo 'SELECT 1' | curl 'http://user:password@localhost:8123/' -d @-
  1. userpassword URL 매개변수에서
매개변수가 웹 프록시에 기록되거나 브라우저에 캐시될 수 있으므로 이 메서드는 권장하지 않습니다
예시:
echo 'SELECT 1' | curl 'http://localhost:8123/?user=user&password=password' -d @-
  1. ‘X-ClickHouse-User’ 및 ‘X-ClickHouse-Key’ 헤더 사용
예를 들어:
echo 'SELECT 1' | curl -H 'X-ClickHouse-User: user' -H 'X-ClickHouse-Key: password' 'http://localhost:8123/' -d @-
사용자 이름을 지정하지 않으면 default 사용자 이름이 사용됩니다. 비밀번호를 지정하지 않으면 빈 비밀번호가 사용됩니다. 또한 URL 매개변수를 사용해 단일 쿼리를 처리하기 위한 설정이나 설정 프로필 전체를 지정할 수 있습니다. 예시:
http://localhost:8123/?profile=web&max_rows_to_read=1000000000&query=SELECT+1
$ echo 'SELECT number FROM system.numbers LIMIT 10' | curl 'http://localhost:8123/?' --data-binary @-
0
1
2
3
4
5
6
7
8
9
자세한 내용은 다음 문서를 참조하십시오:

HTTP 프로토콜에서 ClickHouse 세션 사용하기

HTTP 프로토콜에서도 ClickHouse 세션을 사용할 수 있습니다. 이렇게 하려면 요청에 session_id GET 매개변수를 추가해야 합니다. 세션 ID로는 임의의 문자열을 사용할 수 있습니다. 기본적으로 세션은 60초 동안 비활성 상태이면 종료됩니다. 이 timeout(초 단위)을 변경하려면 서버 구성에서 default_session_timeout 설정을 수정하거나 요청에 session_timeout GET 매개변수를 추가하십시오. 세션 상태를 확인하려면 session_check=1 매개변수를 사용하십시오. 하나의 세션에서는 한 번에 하나의 쿼리만 실행할 수 있습니다. X-ClickHouse-Progress 응답 헤더에서 쿼리 진행 상태 정보를 받을 수 있습니다. 이렇게 하려면 send_progress_in_http_headers를 활성화하십시오. 아래는 헤더 시퀀스의 예시입니다:
X-ClickHouse-Progress: {"read_rows":"261636","read_bytes":"2093088","total_rows_to_read":"1000000","elapsed_ns":"14050417","memory_usage":"22205975"}
X-ClickHouse-Progress: {"read_rows":"654090","read_bytes":"5232720","total_rows_to_read":"1000000","elapsed_ns":"27948667","memory_usage":"83400279"}
X-ClickHouse-Progress: {"read_rows":"1000000","read_bytes":"8000000","total_rows_to_read":"1000000","elapsed_ns":"38002417","memory_usage":"80715679"}
가능한 헤더 필드는 다음과 같습니다.
Header fieldDescription
read_rows읽은 행 수입니다.
read_bytes읽은 데이터의 바이트 단위 크기입니다.
total_rows_to_read읽을 전체 행 수입니다.
written_rows기록한 행 수입니다.
written_bytes기록한 데이터의 바이트 단위 크기입니다.
elapsed_ns쿼리의 나노초 단위 런타임입니다.
memory_usage쿼리에서 사용한 메모리의 바이트 수입니다. (v25.11부터 사용 가능)
실행 중인 요청은 HTTP connection이 끊겨도 자동으로 중단되지 않습니다. 구문 분석과 데이터 포맷팅은 server 측에서 수행되므로 네트워크 사용이 비효율적일 수 있습니다. 다음과 같은 선택적 매개변수가 있습니다.
ParametersDescription
query_id (optional)쿼리 ID로 전달할 수 있습니다(임의의 문자열). replace_running_query
quota_key (optional)쿼터 키로 전달할 수 있습니다(임의의 문자열). “쿼터”
HTTP 인터페이스에서는 쿼리를 위해 외부 데이터(외부 임시 테이블)를 전달할 수 있습니다. 자세한 내용은 “쿼리 처리용 외부 데이터”를 참조하십시오.

응답 버퍼링

응답 버퍼링은 서버 측에서 활성화할 수 있습니다. 이를 위해 다음 URL 매개변수를 사용할 수 있습니다.
  • buffer_size
  • wait_end_of_query
다음 설정도 사용할 수 있습니다. buffer_size는 결과를 서버 메모리에 버퍼링할 바이트 수를 결정합니다. 결과 본문이 이 임계값보다 크면 버퍼는 HTTP 채널에 기록되고, 나머지 데이터는 HTTP 채널로 직접 전송됩니다. 응답 전체가 버퍼링되도록 하려면 wait_end_of_query=1로 설정하십시오. 이 경우 메모리에 저장되지 않는 데이터는 서버의 임시 파일에 버퍼링됩니다. 예시:
curl -sS 'http://localhost:8123/?max_result_bytes=4000000&buffer_size=3000000&wait_end_of_query=1' -d 'SELECT toUInt8(number) FROM system.numbers LIMIT 9000000 FORMAT RowBinary'
응답 코드와 HTTP headers가 클라이언트에 전송된 뒤 쿼리 처리 오류가 발생하는 상황을 방지하려면 버퍼링을 사용하십시오. 이런 경우 오류 메시지는 응답 본문 끝에 기록되며, 클라이언트 측에서는 파싱 단계에서만 오류를 감지할 수 있습니다.

쿼리 매개변수로 역할 설정

이 기능은 ClickHouse 24.4에 추가되었습니다. 특정한 상황에서는 SQL 문 자체를 실행하기 전에 먼저 부여된 역할을 설정해야 할 수 있습니다. 하지만 다중 SQL 문은 허용되지 않으므로 SET ROLE과 SQL 문을 함께 전송할 수 없습니다.
curl -sS "http://localhost:8123" --data-binary "SET ROLE my_role;SELECT * FROM my_table;"
위 명령을 실행하면 다음과 같은 오류가 발생합니다:
Code: 62. DB::Exception: Syntax error (Multi-statements are not allowed)
이 제한을 우회하려면 대신 role 쿼리 매개변수를 사용하십시오:
curl -sS "http://localhost:8123?role=my_role" --data-binary "SELECT * FROM my_table;"
이는 SQL 문을 실행하기 전에 SET ROLE my_role를 실행하는 것과 같습니다. 또한 role 쿼리 매개변수를 여러 개 지정할 수도 있습니다:
curl -sS "http://localhost:8123?role=my_role&role=my_other_role" --data-binary "SELECT * FROM my_table;"
이 경우 ?role=my_role&role=my_other_role는 해당 SQL 문을 실행하기 전에 SET ROLE my_role, my_other_role를 실행하는 것과 비슷하게 동작합니다.

HTTP 응답 코드 관련 주의사항

HTTP 프로토콜의 한계로 인해 HTTP 200 응답 코드가 쿼리 성공을 보장하지는 않습니다. 다음은 예시입니다:
curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)"
*   Trying 127.0.0.1:8123...
...
< HTTP/1.1 200 OK
...
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(number, 2) :: 1) -> throwIf(equals(number, 2))
이러한 동작이 발생하는 이유는 HTTP 프로토콜의 특성 때문입니다. HTTP 헤더가 먼저 HTTP 코드 200과 함께 전송되고, 그다음 HTTP 본문이 전송되며, 이후 오류가 일반 텍스트로 본문에 삽입됩니다. 이 동작은 사용한 포맷과 무관하며, Native, TSV, JSON 중 어떤 것을 사용하든 오류 메시지는 항상 응답 스트림의 중간에 나타납니다. 이 문제는 wait_end_of_query=1(응답 버퍼링)을 활성화하여 완화할 수 있습니다. 이 경우 전체 쿼리 처리가 끝날 때까지 HTTP 헤더 전송이 지연됩니다. 하지만 이렇게 해도 문제가 완전히 해결되지는 않습니다. 결과는 여전히 http_response_buffer_size 안에 들어가야 하며, send_progress_in_http_headers 같은 다른 설정이 헤더 전송 지연에 영향을 줄 수 있기 때문입니다.
모든 오류를 포착하는 유일한 방법은 필요한 포맷으로 파싱하기 전에 HTTP 본문을 분석하는 것입니다.
ClickHouse에서 이러한 예외는 http_write_exception_in_output_format=0(기본값)일 때 사용한 포맷(Native, TSV, JSON 등)과 관계없이 아래와 같이 일관된 예외 포맷을 가집니다. 따라서 클라이언트 측에서 오류 메시지를 파싱하고 추출하기 쉽습니다.
\r\n
__exception__\r\n
<TAG>\r\n
<error message>\r\n
<message_length> <TAG>\r\n
__exception__\r\n

여기서 <TAG>는 16바이트 무작위 태그이며, X-ClickHouse-Exception-Tag 응답 헤더로 전송되는 태그와 동일합니다. <error message>는 실제 예외 메시지입니다(정확한 길이는 <message_length>에서 확인할 수 있습니다). 위에서 설명한 전체 예외 블록의 크기는 최대 16 KiB입니다. 다음은 JSON 포맷 예시입니다.
$ curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)+FORMAT+JSON"
...
{
    "meta":
    [
        {
            "name": "sleepEachRow(0.001)",
            "type": "UInt8"
        },
        {
            "name": "throwIf(equals(number, 2))",
            "type": "UInt8"
        }
    ],

    "data":
    [
        {
            "sleepEachRow(0.001)": 0,
            "throwIf(equals(number, 2))": 0
        },
        {
            "sleepEachRow(0.001)": 0,
            "throwIf(equals(number, 2))": 0
        }
__exception__
dmrdfnujjqvszhav
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(__table1.number, 2_UInt8) :: 1) -> throwIf(equals(__table1.number, 2_UInt8)) UInt8 : 0'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 25.11.1.1)
262 dmrdfnujjqvszhav
__exception__
다음은 CSV 포맷을 사용한 유사한 예시입니다
$ curl -v -Ss "http://localhost:8123/?max_block_size=1&query=select+sleepEachRow(0.001),throwIf(number=2)from+numbers(5)+FORMAT+CSV"
...
<
0,0
0,0

__exception__
rumfyutuqkncbgau
Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(equals(__table1.number, 2_UInt8) :: 1) -> throwIf(equals(__table1.number, 2_UInt8)) UInt8 : 0'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 25.11.1.1)
262 rumfyutuqkncbgau
__exception__

매개변수가 있는 쿼리

매개변수가 있는 쿼리를 생성하고, 해당 값은 대응하는 HTTP 요청 매개변수를 통해 전달할 수 있습니다. 자세한 내용은 CLI용 매개변수가 있는 쿼리를 참조하십시오.

예시

$ curl -sS "<address>?param_id=2&param_phrase=test" -d "SELECT * FROM table WHERE int_column = {id:UInt8} and string_column = {phrase:String}"

URL 매개변수의 탭

쿼리 매개변수는 “escaped” 포맷에서 파싱됩니다. 이 방식에는 \N을 NULL로 명확하게 파싱할 수 있다는 점 등 몇 가지 장점이 있습니다. 즉, 탭 문자는 \t(또는 \와 탭 문자)로 인코딩해야 합니다. 예를 들어, 다음 예시에서는 abc123 사이에 실제 탭이 포함되어 있으므로 입력 문자열이 두 개의 값으로 분할됩니다.
curl -sS "http://localhost:8123" -d "SELECT splitByChar('\t', 'abc      123')"
['abc','123']
하지만 URL 매개변수에서 %09를 사용해 실제 탭 문자를 인코딩하려고 하면 제대로 파싱되지 않습니다:
curl -sS "http://localhost:8123?param_arg1=abc%09123" -d "SELECT splitByChar('\t', {arg1:String})"
Code: 457. DB::Exception: Value abc    123 cannot be parsed as String for query parameter 'arg1' because it isn't parsed completely: only 3 of 7 bytes was parsed: abc. (BAD_QUERY_PARAMETER) (version 23.4.1.869 (official build))
URL 매개변수를 사용하는 경우 \t%5C%09로 인코딩해야 합니다. 예를 들면 다음과 같습니다:
curl -sS "http://localhost:8123?param_arg1=abc%5C%09123" -d "SELECT splitByChar('\t', {arg1:String})"
['abc','123']

미리 정의된 HTTP 인터페이스

ClickHouse는 HTTP 인터페이스를 통해 특정 쿼리를 지원합니다. 예를 들어, 다음과 같이 테이블에 데이터를 쓸 수 있습니다.
$ echo '(4),(5),(6)' | curl 'http://localhost:8123/?query=INSERT%20INTO%20t%20VALUES' --data-binary @-
ClickHouse는 Prometheus exporter와 같은 서드파티 도구와 더 쉽게 통합할 수 있도록 Predefined HTTP Interface도 지원합니다. 예시를 살펴보겠습니다. 먼저 서버 설정 파일에 이 섹션을 추가하십시오. http_handlers는 여러 개의 rule을 포함하도록 구성됩니다. ClickHouse는 수신한 HTTP 요청을 rule에 미리 정의된 유형과 일치시키고, 가장 먼저 일치한 규칙의 핸들러를 실행합니다. 그런 다음 일치에 성공하면 해당하는 미리 정의된 쿼리를 실행합니다.
config.xml
<http_handlers>
    <rule>
        <url>/predefined_query</url>
        <methods>POST,GET</methods>
        <handler>
            <type>predefined_query_handler</type>
            <query>SELECT * FROM system.metrics LIMIT 5 FORMAT Template SETTINGS format_template_resultset = 'prometheus_template_output_format_resultset', format_template_row = 'prometheus_template_output_format_row', format_template_rows_between_delimiter = '\n'</query>
        </handler>
    </rule>
    <rule>...</rule>
    <rule>...</rule>
</http_handlers>
이제 URL을 직접 요청해 Prometheus 포맷의 데이터를 받을 수 있습니다:
$ curl -v 'http://localhost:8123/predefined_query'
*   Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /predefined_query HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 28 Apr 2020 08:52:56 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< X-ClickHouse-Server-Display-Name: i-mloy5trc
< Transfer-Encoding: chunked
< X-ClickHouse-Query-Id: 96fe0052-01e6-43ce-b12a-6b7370de6e8a
< X-ClickHouse-Format: Template
< X-ClickHouse-Timezone: Asia/Shanghai
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
# HELP "Query" "Number of executing queries"
# TYPE "Query" counter
"Query" 1

# HELP "Merge" "Number of executing background merges"
# TYPE "Merge" counter
"Merge" 0

# HELP "PartMutation" "Number of mutations (ALTER DELETE/UPDATE)"
# TYPE "PartMutation" counter
"PartMutation" 0

# HELP "ReplicatedFetch" "Number of data parts being fetched from replica"
# TYPE "ReplicatedFetch" counter
"ReplicatedFetch" 0

# HELP "ReplicatedSend" "Number of data parts being sent to replicas"
# TYPE "ReplicatedSend" counter
"ReplicatedSend" 0

* Connection #0 to host localhost left intact

* Connection #0 to host localhost left intact
http_handlers의 구성 옵션은 다음과 같습니다. rule에서 다음 매개변수를 구성할 수 있습니다.
  • method
  • headers
  • url
  • full_url
  • handler
각 항목은 아래에서 설명합니다.
  • method는 HTTP 요청의 메서드 부분을 매칭합니다. method는 HTTP 프로토콜의 [method] (https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods) 정의를 완전히 따릅니다. 이는 선택적 구성입니다. 설정 파일에 정의하지 않으면 HTTP 요청의 메서드 부분은 매칭하지 않습니다.
  • url은 HTTP 요청의 URL 부분(경로 및 쿼리 문자열)을 매칭합니다. url 앞에 regex: 접두사가 붙으면 RE2 정규식을 사용합니다. 이는 선택적 구성입니다. 설정 파일에 정의하지 않으면 HTTP 요청의 URL 부분은 매칭하지 않습니다.
  • full_urlurl과 같지만 전체 URL, 즉 schema://host:port/path?query_string를 포함합니다. 참고로 ClickHouse는 “virtual hosts”를 지원하지 않으므로 host는 IP 주소이며 Host header의 값이 아닙니다.
  • empty_query_string - 요청에 쿼리 문자열(?query_string)이 없도록 합니다.
  • headers는 HTTP 요청의 헤더 부분을 매칭합니다. RE2 정규식과 호환됩니다. 이는 선택적 구성입니다. 설정 파일에 정의하지 않으면 HTTP 요청의 헤더 부분은 매칭하지 않습니다.
  • handler에는 핵심 처리 로직이 들어 있습니다. 다음 type을 사용할 수 있습니다: 그리고 다음 매개변수를 사용할 수 있습니다:
    • querypredefined_query_handler 유형과 함께 사용하며, 핸들러가 호출될 때 쿼리를 실행합니다.
    • query_param_namedynamic_query_handler 유형과 함께 사용하며, HTTP 요청 매개변수에서 query_param_name에 해당하는 값을 추출해 실행합니다.
    • statusstatic 유형과 함께 사용하며, 응답 상태 코드입니다.
    • content_type — 모든 유형과 함께 사용하며, 응답 content-type입니다.
    • http_response_headers — 모든 유형과 함께 사용하며, 응답 헤더 맵입니다. content type 설정에도 사용할 수 있습니다.
    • response_contentstatic 유형과 함께 사용하며, 클라이언트로 전송되는 응답 콘텐츠입니다. ‘file://’ 또는 ‘config://’ 접두사를 사용하면 콘텐츠를 파일이나 구성에서 찾아 클라이언트로 전송합니다.
    • user - 쿼리를 실행할 사용자입니다(기본 사용자는 default). 참고: 이 사용자의 비밀번호는 지정할 필요가 없습니다.
서로 다른 type에 대한 구성 방법은 다음에서 설명합니다.

predefined_query_handler

predefined_query_handlerSettingsquery_params 값 설정을 지원합니다. predefined_query_handler 타입에서 query를 구성할 수 있습니다. query 값은 predefined_query_handler의 미리 정의된 쿼리이며, HTTP 요청과 일치하면 ClickHouse가 이를 실행하고 쿼리 결과를 반환합니다. 반드시 지정해야 하는 구성입니다. 다음 예시는 max_threadsmax_final_threads 설정 값을 지정한 다음, 시스템 테이블(system table)을 쿼리하여 이러한 설정이 성공적으로 적용되었는지 확인합니다.
query, play, ping과 같은 기본 handlers를 유지하려면 <defaults/> 규칙을 추가하십시오.
예시:
<http_handlers>
    <rule>
        <url><![CDATA[regex:/query_param_with_url/(?P<name_1>[^/]+)]]></url>
        <methods>GET</methods>
        <headers>
            <XXX>TEST_HEADER_VALUE</XXX>
            <PARAMS_XXX><![CDATA[regex:(?P<name_2>[^/]+)]]></PARAMS_XXX>
        </headers>
        <handler>
            <type>predefined_query_handler</type>
            <query>
                SELECT name, value FROM system.settings
                WHERE name IN ({name_1:String}, {name_2:String})
            </query>
        </handler>
    </rule>
    <defaults/>
</http_handlers>
curl -H 'XXX:TEST_HEADER_VALUE' -H 'PARAMS_XXX:max_final_threads' 'http://localhost:8123/query_param_with_url/max_threads?max_threads=1&max_final_threads=2'
max_final_threads    2
max_threads    1

가상 매개변수 _request_body

predefined_query_handler는 URL 매개변수, 헤더, 쿼리 매개변수 외에도 특수한 가상 매개변수 _request_body를 지원합니다. 이 매개변수에는 원시 HTTP 요청 본문이 문자열로 포함됩니다. 이를 통해 임의의 데이터 포맷을 받아 쿼리 내에서 처리할 수 있는 유연한 REST API를 만들 수 있습니다. 예를 들어, _request_body를 사용하면 POST 요청으로 JSON 데이터를 받아 테이블에 삽입하는 REST 엔드포인트를 구현할 수 있습니다:
<http_handlers>
    <rule>
        <methods>POST</methods>
        <url>/api/events</url>
        <handler>
            <type>predefined_query_handler</type>
            <query>
                INSERT INTO events (id, data)
                SELECT {id:UInt32}, {_request_body:String}
            </query>
        </handler>
    </rule>
    <defaults/>
</http_handlers>
다음으로, 이 엔드포인트로 데이터를 전송할 수 있습니다:
curl -X POST 'http://localhost:8123/api/events?id=123' \
  -H 'Content-Type: application/json' \
  -d '{"user": "john", "action": "login", "timestamp": "2024-01-01T10:00:00Z"}'
predefined_query_handler 하나당 지원되는 query는 하나뿐입니다.

dynamic_query_handler

dynamic_query_handler에서는 HTTP 요청의 매개변수 형식으로 쿼리를 작성합니다. predefined_query_handler와의 차이점은 predefined_query_handler에서는 쿼리를 설정 파일에 작성한다는 것입니다. query_param_namedynamic_query_handler에서 구성할 수 있습니다. ClickHouse는 HTTP 요청 URL에서 query_param_name에 해당하는 값을 추출해 실행합니다. query_param_name의 기본값은 /query입니다. 이는 선택적 구성입니다. 설정 파일에 정의되어 있지 않으면 이 매개변수는 전달되지 않습니다. 이 기능을 시험해 보기 위해, 다음 예시에서는 max_threadsmax_final_threads 값을 정의하고, 설정이 올바르게 적용되었는지 queries로 확인합니다. 예시:
<http_handlers>
    <rule>
    <headers>
        <XXX>TEST_HEADER_VALUE_DYNAMIC</XXX>    </headers>
    <handler>
        <type>dynamic_query_handler</type>
        <query_param_name>query_param</query_param_name>
    </handler>
    </rule>
    <defaults/>
</http_handlers>
curl  -H 'XXX:TEST_HEADER_VALUE_DYNAMIC'  'http://localhost:8123/own?max_threads=1&max_final_threads=2&param_name_1=max_threads&param_name_2=max_final_threads&query_param=SELECT%20name,value%20FROM%20system.settings%20where%20name%20=%20%7Bname_1:String%7D%20OR%20name%20=%20%7Bname_2:String%7D'
max_threads 1
max_final_threads   2

static

staticcontent_type, status, response_content를 반환할 수 있습니다. response_content는 지정된 내용을 반환합니다. 예를 들어, “Say Hi!” 메시지를 반환하려면:
<http_handlers>
        <rule>
            <methods>GET</methods>
            <headers><XXX>xxx</XXX></headers>
            <url>/hi</url>
            <handler>
                <type>static</type>
                <status>402</status>
                <content_type>text/html; charset=UTF-8</content_type>
                <http_response_headers>
                    <Content-Language>en</Content-Language>
                    <X-My-Custom-Header>43</X-My-Custom-Header>
                </http_response_headers>
                <response_content>Say Hi!</response_content>
            </handler>
        </rule>
        <defaults/>
</http_handlers>
http_response_headers를 사용하면 content_type 대신 콘텐츠 유형을 지정할 수 있습니다.
<http_handlers>
        <rule>
            <methods>GET</methods>
            <headers><XXX>xxx</XXX></headers>
            <url>/hi</url>
            <handler>
                <type>static</type>
                <status>402</status>
                #begin-highlight
                <http_response_headers>
                    <Content-Type>text/html; charset=UTF-8</Content-Type>
                    <Content-Language>en</Content-Language>
                    <X-My-Custom-Header>43</X-My-Custom-Header>
                </http_response_headers>
                #end-highlight
                <response_content>Say Hi!</response_content>
            </handler>
        </rule>
        <defaults/>
</http_handlers>
curl -vv  -H 'XXX:xxx' 'http://localhost:8123/hi'
*   Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /hi HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 402 Payment Required
< Date: Wed, 29 Apr 2020 03:51:26 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
* Connection #0 to host localhost left intact
Say Hi!%
구성에서 클라이언트로 전송할 콘텐츠를 찾습니다.
<get_config_static_handler><![CDATA[<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>]]></get_config_static_handler>

<http_handlers>
        <rule>
            <methods>GET</methods>
            <headers><XXX>xxx</XXX></headers>
            <url>/get_config_static_handler</url>
            <handler>
                <type>static</type>
                <response_content>config://get_config_static_handler</response_content>
            </handler>
        </rule>
</http_handlers>
$ curl -v  -H 'XXX:xxx' 'http://localhost:8123/get_config_static_handler'
*   Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_config_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:01:24 GMT
< Connection: Keep-Alive
< Content-Type: text/plain; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
* Connection #0 to host localhost left intact
<html ng-app="SMI2"><head><base href="http://ui.tabix.io/"></head><body><div ui-view="" class="content-ui"></div><script src="http://loader.tabix.io/master.js"></script></body></html>%
클라이언트로 전송되는 파일의 내용을 확인하려면:
<http_handlers>
        <rule>
            <methods>GET</methods>
            <headers><XXX>xxx</XXX></headers>
            <url>/get_absolute_path_static_handler</url>
            <handler>
                <type>static</type>
                <content_type>text/html; charset=UTF-8</content_type>
                <http_response_headers>
                    <ETag>737060cd8c284d8af7ad3082f209582d</ETag>
                </http_response_headers>
                <response_content>file:///absolute_path_file.html</response_content>
            </handler>
        </rule>
        <rule>
            <methods>GET</methods>
            <headers><XXX>xxx</XXX></headers>
            <url>/get_relative_path_static_handler</url>
            <handler>
                <type>static</type>
                <content_type>text/html; charset=UTF-8</content_type>
                <http_response_headers>
                    <ETag>737060cd8c284d8af7ad3082f209582d</ETag>
                </http_response_headers>
                <response_content>file://./relative_path_file.html</response_content>
            </handler>
        </rule>
</http_handlers>
$ user_files_path='/var/lib/clickhouse/user_files'
$ sudo echo "<html><body>Relative Path File</body></html>" > $user_files_path/relative_path_file.html
$ sudo echo "<html><body>Absolute Path File</body></html>" > $user_files_path/absolute_path_file.html
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/get_absolute_path_static_handler'
*   Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_absolute_path_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:18:16 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
<html><body>Absolute Path File</body></html>
* Connection #0 to host localhost left intact
$ curl -vv -H 'XXX:xxx' 'http://localhost:8123/get_relative_path_static_handler'
*   Trying ::1...
* Connected to localhost (::1) port 8123 (#0)
> GET /get_relative_path_static_handler HTTP/1.1
> Host: localhost:8123
> User-Agent: curl/7.47.0
> Accept: */*
> XXX:xxx
>
< HTTP/1.1 200 OK
< Date: Wed, 29 Apr 2020 04:18:31 GMT
< Connection: Keep-Alive
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Keep-Alive: timeout=10
< X-ClickHouse-Summary: {"read_rows":"0","read_bytes":"0","written_rows":"0","written_bytes":"0","total_rows_to_read":"0","elapsed_ns":"662334","memory_usage":"8451671"}
<
<html><body>Relative Path File</body></html>
* Connection #0 to host localhost left intact

redirect

redirectlocation으로 302 리디렉션을 수행합니다. 예를 들어 ClickHouse play에서 play에 set user를 자동으로 추가하려면 다음과 같이 합니다:
<clickhouse>
    <http_handlers>
        <rule>
            <methods>GET</methods>
            <url>/play</url>
            <handler>
                <type>redirect</type>
                <location>/play?user=play</location>
            </handler>
        </rule>
    </http_handlers>
</clickhouse>

HTTP 응답 헤더

ClickHouse에서는 구성할 수 있는 모든 유형의 핸들러에 적용할 사용자 지정 HTTP 응답 헤더를 설정할 수 있습니다. 이러한 헤더는 헤더 이름과 해당 값을 나타내는 key-value 쌍을 받는 http_response_headers 설정으로 지정할 수 있습니다. 이 기능은 ClickHouse HTTP 인터페이스 전반에서 사용자 지정 보안 헤더, CORS 정책 또는 기타 HTTP 헤더 요구 사항을 구현할 때 특히 유용합니다. 예를 들어, 다음에 대한 헤더를 구성할 수 있습니다.
  • 일반 쿼리 엔드포인트
  • 웹 UI
  • 상태 확인
또한 common_http_response_headers를 지정할 수도 있습니다. 이는 구성에 정의된 모든 HTTP 핸들러에 적용됩니다. 헤더는 구성된 각 핸들러의 HTTP 응답에 포함됩니다. 아래 예시에서는 모든 서버 응답에 X-My-Common-HeaderX-My-Custom-Header라는 두 개의 사용자 지정 헤더가 포함됩니다.
<clickhouse>
    <http_handlers>
        <common_http_response_headers>
            <X-My-Common-Header>Common header</X-My-Common-Header>
        </common_http_response_headers>
        <rule>
            <methods>GET</methods>
            <url>/ping</url>
            <handler>
                <type>ping</type>
                <http_response_headers>
                    <X-My-Custom-Header>Custom indeed</X-My-Custom-Header>
                </http_response_headers>
            </handler>
        </rule>
    </http_handlers>
</clickhouse>

HTTP streaming 중 예외 발생 시 유효한 JSON/XML 응답

HTTP를 통해 쿼리를 실행하는 동안 데이터의 일부가 이미 전송된 후 예외가 발생할 수 있습니다. 일반적으로 예외는 일반 텍스트로 클라이언트에 전송됩니다. 데이터를 출력할 때 특정 데이터 포맷을 사용했더라도, 그 결과가 지정된 데이터 포맷 기준으로는 유효하지 않게 될 수 있습니다. 이를 방지하려면 http_write_exception_in_output_format 설정(기본적으로 비활성화됨)을 사용할 수 있습니다. 이 설정을 사용하면 ClickHouse가 지정된 포맷으로 예외를 기록합니다(현재 XML 및 JSON* 포맷 지원). 예시:
$ curl 'http://localhost:8123/?query=SELECT+number,+throwIf(number>3)+from+system.numbers+format+JSON+settings+max_block_size=1&http_write_exception_in_output_format=1'
{
    "meta":
    [
        {
            "name": "number",
            "type": "UInt64"
        },
        {
            "name": "throwIf(greater(number, 2))",
            "type": "UInt8"
        }
    ],

    "data":
    [
        {
            "number": "0",
            "throwIf(greater(number, 2))": 0
        },
        {
            "number": "1",
            "throwIf(greater(number, 2))": 0
        },
        {
            "number": "2",
            "throwIf(greater(number, 2))": 0
        }
    ],

    "rows": 3,

    "exception": "Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 2) :: 2) -> throwIf(greater(number, 2)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 23.8.1.1)"
}
$ curl 'http://localhost:8123/?query=SELECT+number,+throwIf(number>2)+from+system.numbers+format+XML+settings+max_block_size=1&http_write_exception_in_output_format=1'
<?xml version='1.0' encoding='UTF-8' ?>
<result>
    <meta>
        <columns>
            <column>
                <name>number</name>
                <type>UInt64</type>
            </column>
            <column>
                <name>throwIf(greater(number, 2))</name>
                <type>UInt8</type>
            </column>
        </columns>
    </meta>
    <data>
        <row>
            <number>0</number>
            <field>0</field>
        </row>
        <row>
            <number>1</number>
            <field>0</field>
        </row>
        <row>
            <number>2</number>
            <field>0</field>
        </row>
    </data>
    <rows>3</rows>
    <exception>Code: 395. DB::Exception: Value passed to 'throwIf' function is non-zero: while executing 'FUNCTION throwIf(greater(number, 2) :: 2) -> throwIf(greater(number, 2)) UInt8 : 1'. (FUNCTION_THROW_IF_VALUE_IS_NON_ZERO) (version 23.8.1.1)</exception>
</result>
마지막 수정일 2026년 6월 10일