메인 콘텐츠로 건너뛰기
clickhouse-jdbc는 최신 Java 클라이언트를 사용해 표준 JDBC 인터페이스를 구현합니다. 성능이나 직접 접근이 중요하다면 최신 Java 클라이언트를 직접 사용할 것을 권장합니다.

환경 요구 사항

Setup

애플리케이션에서 JDBC 드라이버를 사용할 때 classpath에 jar를 추가해야 하는 경우, 다음 위치에서 jar를 다운로드하십시오:

구성

드라이버 클래스: com.clickhouse.jdbc.ClickHouseDriver
com.clickhouse.jdbc.ClickHouseDriver는 신규 및 기존 JDBC 구현을 위한 파사드 클래스입니다. 기본적으로는 신규 JDBC 구현을 사용합니다. 기존 JDBC 구현을 사용하려면 clickhouse.jdbc.v1 system 속성을 true로 설정할 수 있습니다. 이 속성은 Driver 클래스를 호출하기 전에 설정해야 합니다.버전을 전환하는 다른 방법은 각 버전의 Driver 클래스를 직접 사용하는 것입니다:
  • com.clickhouse.jdbc.Driver는 신규 JDBC 구현(V2)입니다.
  • com.clickhouse.jdbc.DriverV1는 기존 JDBC 구현(V1)입니다.
URL 구문: jdbc:(ch|clickhouse)[:<protocol>]://endpoint[:port][/<database>][?param1=value1&param2=value2][#tag1,tag2,...], 예시:
  • jdbc:clickhouse:http://localhost:8123
  • jdbc:clickhouse:https://localhost:8443?ssl=true
URL 구문에서 주의해야 할 사항이 몇 가지 있습니다:
  • URL에는 단 하나의 엔드포인트만 허용됩니다
  • 프로토콜은 기본값인 ‘HTTP’가 아닌 경우에만 지정해야 합니다
  • 포트가 기본값인 ‘8123’이 아닌 경우 포트를 지정해야 합니다
  • 드라이버는 포트 번호만 보고 프로토콜을 추측하지 않으므로, 프로토콜을 명시적으로 지정해야 합니다
  • protocol이 지정된 경우 ssl 매개변수는 필요하지 않습니다.

연결(Connection) 속성

주요 구성 매개변수는 Java 클라이언트에 정의되어 있습니다. 해당 매개변수는 그대로 드라이버에 전달하면 됩니다. 드라이버에는 클라이언트 구성에 포함되지 않는 고유 속성이 있으며, 아래에 나열되어 있습니다.드라이버 속성:
서버 설정모든 서버 설정에는 clickhouse_setting_ 접두사를 사용해야 합니다(클라이언트 구성과 동일).
예시 구성:
다음 JDBC URL과 동일합니다:
참고: JDBC URL 또는 속성을 URL 인코딩할 필요가 없습니다. 자동으로 인코딩됩니다.

클라이언트 식별

요청을 발생시킨 애플리케이션을 식별하는 방법은 두 가지입니다. 연결(connection) 속성을 통해 com.clickhouse.client.api.ClientConfigProperties#CLIENT_NAME을 설정하거나, java.sql.Connection#setClientInfo(String name, String value) 메서드를 사용하십시오.
showLineNumbers
showLineNumbers
두 방법 모두 쿼리 로그에 다음과 같은 http_user_agent 값을 생성합니다:
참고: client_name 속성에는 app_name/version 포맷을 사용하는 것을 권장합니다. 이렇게 하면 쿼리 로그에서 애플리케이션을 식별하는 데 도움이 됩니다.

작업 식별

JDBC 드라이버는 각 작업마다 query_id를 생성합니다(현재는 서버 예외(Exception)에 포함되어 있습니다).작업에 log_comment를 설정하려면 com.clickhouse.jdbc.StatementImpl#getLocalSettings 메서드를 사용하십시오. 이 메서드를 사용하려면 먼저 Statement 또는 PreparedStatementcom.clickhouse.jdbc.StatementImpl로 캐스팅해야 합니다.
showLineNumbers
참고: localSettings가 스레드 간에 공유되므로, 이 방식은 단일 스레드에서 statement를 사용하는 경우에만 적용됩니다.

지원되는 데이터 타입

JDBC 드라이버는 기반 Java 클라이언트와 동일한 데이터 포맷을 지원합니다.

JDBC 유형 매핑

다음 매핑이 적용되는 대상:
  • ResultSet#getObject(columnIndex) - 메서드는 해당 Java 클래스에 대응하는 객체를 반환합니다. (Int8 -> java.lang.Byte, Int16 -> java.lang.Short 등)
  • ResultSetMetaData#getColumnType(columnIndex) - 메서드는 해당 JDBC 타입을 반환합니다. (Int8 -> java.lang.Byte, Int16 -> java.lang.Short 등)
매핑을 변경하는 방법에는 몇 가지가 있습니다:
  • ResultSet#getObject(columnIndex, class) - 메서드는 값을 class 타입으로 변환합니다. 일부 변환에는 제한 사항이 있습니다. 자세한 내용은 각 섹션을 참조하십시오.
숫자 타입
  • 숫자 타입은 서로 변환할 수 있습니다. 따라서 Int8Float64로 읽을 수 있으며, 그 반대도 가능합니다.:
    • rs.getObject(1, Float64.class)Int8 컬럼의 Float64 값을 반환합니다.
    • rs.getLong(1)Int8 컬럼의 Long 값을 반환합니다.
    • rs.getByte(1)는 값이 Byte 범위에 맞으면 Int16 컬럼의 Byte 값을 반환할 수 있습니다.
  • 더 넓은 범위의 자료형에서 더 좁은 범위의 자료형으로 변환하는 것은 데이터 손상 위험이 있어 권장되지 않습니다.
  • Bool 유형은 숫자 역할도 합니다.
  • 모든 숫자 타입은 java.lang.String으로 읽을 수 있습니다.
  • Java Float.MAX_VALUEFloat로 저장하면 문제가 발생합니다(https://github.com/ClickHouse/clickhouse-java/issues/809). 동일한 값을 Double로 저장하면 문제가 해결됩니다.
문자열 타입
  • Stringjava.lang.String 또는 byte[] 형식으로만 읽을 수 있습니다.
  • FixedString은 있는 그대로 읽히며, 컬럼 길이에 맞게 0으로 채워집니다. (예를 들어 'John'에 대한 FixedString(10)'John\0\0\0\0\0\0\0\0\0'으로 읽힙니다.)
Enum 타입
  • Enum8Enum16은 기본적으로 java.lang.String으로 매핑됩니다.
  • Enum 값은 지정된 getter 메서드나 getObject(columnIndex, Integer.class) 메서드를 사용해 숫자 값으로 읽을 수 있습니다.
  • Enum16은 내부적으로 short로 매핑되고 Enum8은 byte로 매핑됩니다. 데이터 손상 위험이 있으므로 Enum16을 byte로 읽지 않아야 합니다.
  • PreparedStatement에서는 Enum 값을 문자열이나 숫자 값으로 설정할 수 있습니다.
날짜/시간 타입
  • Date / Time 타입은 JDBC와의 호환성을 높이기 위해 java.sql 타입에 매핑됩니다. 하지만 두 번째 인수로 해당 클래스를 지정해 ResultSet#getObject(columnIndex, Class<T>)를 사용하면 java.time.LocalDate, java.time.LocalDateTime, java.time.LocalTime도 가져올 수 있습니다.
    • rs.getObject(1, java.time.LocalDate.class)Date 컬럼 값을 java.time.LocalDate로 반환합니다.
    • rs.getObject(1, java.time.LocalDateTime.class)DateTime 컬럼 값을 java.time.LocalDateTime으로 반환합니다.
    • rs.getObject(1, java.time.LocalTime.class)Time 컬럼 값을 java.time.LocalTime으로 반환합니다.
  • Date, Date32, Time, Time64는 서버 시간대의 영향을 받지 않습니다.
  • DateTime, DateTime64는 서버의 시간대 또는 세션 시간대의 영향을 받습니다.
  • DateTimeDateTime64getObject(colIndex, ZonedDateTime.class)를 사용해 ZonedDateTime으로 가져올 수 있습니다.
중첩 타입
  • 기본적으로 Array는 JDBC와의 호환성을 위해 java.sql.Array에 매핑됩니다. 이는 반환되는 배열 값에 관한 더 많은 정보를 제공하기 위한 것이기도 합니다. 유형 추론에 유용합니다.
  • Array는 원래 배열과 동일한 내용을 담은 java.sql.ResultSet을 반환하도록 getResultSet() 메서드를 구현합니다.
  • 컬렉션 타입은 데이터를 올바르게 표현하는 방식이 아니므로 java.lang.String으로 읽어서는 안 됩니다(예: 배열의 문자열 값에는 따옴표가 없습니다).
  • Map의 값은 getObject(columnIndex, Class<T>) 메서드로만 읽을 수 있으므로 JAVA_OBJECT에 매핑됩니다.
    • Map은 이름이 있는 컬럼이 없으므로 java.sql.Struct가 아닙니다.
  • Tuple은 서로 다른 타입을 포함할 수 있으며 List는 사용할 수 없기 때문에 Object[]로 매핑됩니다.
  • TuplegetObject(columnIndex, Array.class) 메서드를 사용해 Array로 읽을 수 있습니다. 이 경우 Array#baseTypeNameTuple 컬럼의 정의를 반환합니다.
배열 쓰기java.sql.Array 객체를 인스턴스화하려면 java.sql.Connection#createArrayOf를 사용하십시오. 이 객체는 서로 다른 데이터베이스 간의 배열 처리를 통합하기 위해 설계되었습니다. Array 팩토리 메서드에 구성을 전달하려면 Connection이 필요합니다.이 메서드는 두 개의 인수를 받습니다:
  • typeName - 배열 요소의 타입 이름입니다. 예를 들어 Array(Int32) -> "Int32"입니다.
  • elements - 실제 배열 요소입니다. 예를 들어 [[1, 2, 3], [4, 5, 6]]new Integer[][] {{1, 2, 3}, {4, 5, 6}}입니다.
튜플은 Object[] 또는 java.sql.Struct로 표현할 수 있습니다 (튜플 작성 방법은 아래를 참조하세요).예시
배열 읽기ResultSet#getArray(columnIndex)를 사용하여 Array 객체를 읽으십시오. 이 객체를 통해 임의의 중첩 깊이를 가진 배열에 접근할 수 있습니다. Array#getResultSet() 메서드를 사용하면 배열 요소를 java.sql.ResultSet 형태로 보다 일관된 방식으로 읽을 수 있습니다. 배열 요소의 정확한 유형을 알 수 없을 때 유용합니다.예시
튜플 작성튜플은 com.clickhouse.data.Tuple 객체에 매핑되며, setObject(columnIndex, tuple) 메서드를 호출하여 해당 객체로 작성해야 합니다. 이식성을 높이기 위해 java.sql.Struct 객체를 사용하여 튜플을 작성할 수도 있습니다.예시
튜플 읽기getObject(columnIndex) 메서드는 Object[]를 반환합니다. 튜플은 getObject(columnIndex, Array.class) 메서드를 사용하여 java.sql.Array로 읽을 수 있습니다.예시
맵 쓰기맵(Map)은 key-value 쌍을 필요로 하는 타입이므로 java.collections.Map 객체로만 작성할 수 있습니다(java.sql.Struct는 key-value 쌍을 지원하지 않습니다).예시
맵 읽기맵은 getObject(columnIndex, Map.class) 메서드를 사용하여 java.collections.Map 객체로 읽을 수 있습니다.예시
중첩 데이터 쓰기java.sql.Connection#createStruct를 사용하여 java.sql.Struct 객체를 인스턴스화하십시오. 이 객체는 서로 다른 데이터베이스 간의 중첩 처리를 통합하기 위해 설계되었습니다. Struct 팩토리 메서드에 구성을 전달하려면 Connection이 필요합니다.이 메서드는 두 개의 인수를 받습니다:
  • typeName - 중첩된 요소의 유형 이름입니다. 예를 들어 Nested(Tuple(Int32, String)) -> "Nested(Tuple(Int32, String))"입니다.
  • elements - 실제 중첩된 요소입니다. 예를 들어 [1, 'test'] -> new Object[] {1, 'test'}입니다.
예시
중첩 읽기ResultSet#getStruct(columnIndex, StructDescriptor)를 사용하여 Nested 객체를 읽으십시오. 이 객체를 통해 임의의 중첩 깊이에 있는 중첩 데이터에 접근할 수 있습니다. Struct#getResultSet() 메서드를 사용하면 중첩 요소를 java.sql.ResultSet과 동일한 방식으로 읽을 수 있습니다. 중첩 요소의 정확한 유형을 알 수 없을 때 유용합니다.예시
Geo 타입널 허용(Nullable) 및 LowCardinality 타입
  • NullableLowCardinality는 다른 타입을 감싸는 특수 타입입니다.
  • NullableResultSetMetaData에서 타입 이름이 반환되는 방식에 영향을 미칩니다
특수 타입
  • UUID는 JDBC 표준 유형이 아닙니다. 하지만 JDK에 포함되어 있습니다. 기본적으로 getObject() 메서드는 java.util.UUID를 반환합니다.
  • UUIDgetObject(columnIndex, String.class) 메서드로 String으로 읽고 쓸 수 있습니다.
  • IPv4IPv6는 JDBC 표준 타입이 아닙니다. 하지만 JDK에는 포함되어 있습니다. 기본적으로 getObject() 메서드는 java.net.Inet4Addressjava.net.Inet6Address를 반환합니다.
  • getObject(columnIndex, String.class) 메서드를 사용하면 IPv4IPv6String으로 읽고 쓸 수 있습니다.

날짜, 시간 및 시간대 처리

Date/Time 및 Timestamps 처리 시 흔히 발생하는 문제점과 드라이버의 동작 방식을 설명하는 Date/Time Guide를 참고하십시오.

연결(Connection) 생성

자격 증명 및 설정 제공

showLineNumbers

간단한 구문(Statement)

showLineNumbers

삽입

showLineNumbers

HikariCP

showLineNumbers

추가 정보

자세한 내용은 GitHub 리포지토리Java 클라이언트 문서를 참조하십시오.

문제 해결

로깅

드라이버는 로깅에 slf4j를 사용하며, classpath에서 사용 가능한 첫 번째 구현체를 사용합니다.

대용량 삽입 시 JDBC 타임아웃 해결

ClickHouse에서 실행 시간이 긴 대용량 삽입(insert) 작업을 수행할 때 다음과 같은 JDBC 타임아웃 오류가 발생할 수 있습니다:
이러한 오류는 데이터 삽입 프로세스를 방해하고 시스템 안정성에 영향을 미칠 수 있습니다. 이 문제를 해결하려면 클라이언트 OS의 timeout 설정을 일부 조정해야 할 수 있습니다.

Mac OS

Mac OS에서는 다음 설정을 조정하여 문제를 해결할 수 있습니다.
  • net.inet.tcp.keepidle: 60000
  • net.inet.tcp.keepintvl: 45000
  • net.inet.tcp.keepinit: 45000
  • net.inet.tcp.keepcnt: 8
  • net.inet.tcp.always_keepalive: 1

Linux

Linux에서는 동일한 설정만으로는 문제가 해결되지 않을 수 있습니다. Linux의 소켓 연결 유지 설정 처리 방식이 다르기 때문에 추가적인 단계가 필요합니다. 다음 단계를 따르십시오.
  1. 다음 Linux 커널 매개변수를 /etc/sysctl.conf 또는 관련 설정 파일에서 조정하세요:
  • net.inet.tcp.keepidle: 60000
  • net.inet.tcp.keepintvl: 45000
  • net.inet.tcp.keepinit: 45000
  • net.inet.tcp.keepcnt: 8
  • net.inet.tcp.always_keepalive: 1
  • net.ipv4.tcp_keepalive_intvl: 75
  • net.ipv4.tcp_keepalive_probes: 9
  • net.ipv4.tcp_keepalive_time: 60 (기본값인 300초에서 이 값을 더 낮추는 것을 고려할 수 있습니다)
  1. 커널 매개변수를 수정한 후 다음 명령을 실행하여 변경 사항을 적용하십시오:
해당 설정을 적용한 후에는 클라이언트가 소켓에서 Keep Alive 옵션을 활성화하는지 확인하십시오:

마이그레이션 가이드

주요 변경 사항

  • JDBC V2는 더 경량화되도록 구현되었으며, 일부 기능은 제거되었습니다.
    • 스트리밍 데이터는 JDBC 사양 및 Java 자체에 포함되지 않으므로 JDBC V2에서는 지원되지 않습니다.
  • JDBC V2는 명시적인 구성이 필요합니다. failover 기본값은 없습니다.
    • URL에 protocol을 명시해야 합니다. 포트 번호를 이용한 암묵적 protocol 감지는 지원하지 않습니다.

구성 변경 사항

enum은 두 가지뿐입니다:
  • com.clickhouse.jdbc.DriverProperties - 드라이버 고유의 구성 속성입니다.
  • com.clickhouse.client.api.ClientConfigProperties - 클라이언트 구성 속성입니다. 클라이언트 구성 변경 사항은 Java 클라이언트 문서에 설명되어 있습니다.
연결(Connection) 속성은 다음과 같이 파싱(parse)됩니다:
  • 먼저 URL에서 속성을 파싱합니다. 이렇게 파싱된 속성은 다른 모든 속성을 재정의합니다.
  • 드라이버 속성은 클라이언트로 전달되지 않습니다.
  • 엔드포인트(host, port, protocol)는 URL에서 파싱됩니다.
예시:

데이터 타입 변경 사항

숫자 타입
  • 가장 큰 차이점은 이식성을 높이기 위해 부호 없는 타입이 Java 타입으로 매핑된다는 점입니다.
문자열 타입
  • 두 버전 모두에서 FixedString은 그대로 읽습니다. 예를 들어 'John'FixedString(10)'John\0\0\0\0\0\0\0\0\0'으로 읽습니다.
  • PreparedStatement#setBytes를 사용하면 unhex('<hex_string>')로 변환된 후 String으로 읽습니다.
  • 문자열은 UTF-8 인코딩으로 저장됩니다.
날짜/시간 타입
  • TimeTime64는 V2에서만 새 타입으로 지원됩니다.
  • DateTimeDateTime64는 JDBC와의 호환성을 높이기 위해 java.sql.Timestamp로 매핑됩니다.
Enum 타입중첩 타입
  • V2에서는 JDBC와의 호환성을 위해 기본적으로 Arrayjava.sql.Array에 매핑합니다. 이렇게 하면 반환되는 배열 값에 대한 정보를 더 많이 제공할 수 있습니다. 유형 추론에 유용합니다.
  • V2에서는 ArraygetResultSet() 메서드를 구현하여 원본 배열과 동일한 내용을 담은 java.sql.ResultSet을 반환합니다.
  • V1은 MapSTRUCT를 사용하지만, 항상 java.util.Map 객체를 반환합니다. V2는 MapJAVA_OBJECT로 매핑해 이 문제를 해결합니다.
  • V1에서는 TupleSTRUCT를 사용하지만, 항상 List<Object> 객체를 반환합니다. V2에서는 TupleOTHER로 매핑하며, 기본적으로 Object[]를 반환합니다.
  • V2에서는 튜플을 기록하기 위해 com.clickhouse.data.Tuple#Tuple를 도입합니다. 값이 튜플인지 배열인지 판별하는 작업을 단순화합니다.
  • PreparedStatement#setBytesResultSet#getBytes는 컬렉션 타입에는 사용할 수 없습니다. 이 메서드들은 바이너리 문자열에서 작동하도록 설계되었습니다.
  • 일반적으로 배열(Array) 타입을 읽고 쓸 때는 java.sql.Array를 사용합니다. JDBC 드라이버는 이를 완벽하게 지원합니다.
  • V2 NestedArray로 매핑되며, 튜플 배열로 표시됩니다.
  • V2는 java.sql.Struct가 배열과 매우 유사하고 key-value 쌍을 지원하지 않으므로 부분적으로만 지원합니다. StructTuple 값을 쓰는 데 사용할 수 있습니다.
Geo 타입널 허용(Nullable) 및 LowCardinality 타입
  • NullableLowCardinality는 다른 타입을 감싸는 특수 타입입니다.
  • V2에서는 이러한 타입에 변경이 없습니다.
특수 타입
  • V1은 UUIDVARCHAR를 사용하지만, 항상 java.util.UUID 객체를 반환합니다. V2는 UUIDOTHER로 매핑해 이 문제를 해결하고, java.util.UUID 객체를 반환합니다.
  • V1은 IPv4IPv6VARCHAR를 사용하지만, 반환값은 항상 java.net.Inet4Addressjava.net.Inet6Address 객체입니다. V2는 IPv4IPv6OTHER로 매핑해 이 문제를 해결했으며, java.net.Inet4Addressjava.net.Inet6Address 객체를 반환합니다.
  • DynamicVariant는 V2에서 새로 도입된 타입입니다. V1에서는 지원되지 않습니다.
  • JSONDynamic 타입을 기반으로 합니다. 따라서 V2에서만 지원됩니다.
  • IPv4 및 IPv6 값은 getBytes(columnIndex) 메서드를 사용해 byte[]로 읽을 수 있습니다. 그러나 이러한 타입에는 전용 클래스를 사용하는 것이 좋습니다.
  • V2는 IP 주소를 숫자 값으로 읽는 기능을 지원하지 않습니다. 변환은 InetAddress 클래스에서 처리하는 편이 더 적절하기 때문입니다.

데이터베이스 메타데이터 변경 사항

  • V2에서는 데이터베이스를 지칭하는 용어로 Schema만 사용합니다. Catalog는 향후 사용을 위해 예약되어 있습니다.
  • V2는 DatabaseMetaData.supportsTransactions()DatabaseMetaData.supportsSavepoints()에 대해 false를 반환합니다. 이 동작은 향후 개발 과정에서 변경될 예정입니다.
마지막 수정일 2026년 6월 19일