연결
다음 예시는 server 버전을 반환하며, ClickHouse에 보안이 설정되어 있지 않고default 사용자로 접근할 수 있다고 가정할 때 ClickHouse에 연결하는 방법을 보여줍니다.
연결에는 기본 네이티브 포트를 사용합니다.
conn 변수가 이미 생성되어 사용 가능한 상태라고 가정합니다.
실행
임의의 SQL 문은Exec 메서드로 실행할 수 있습니다. 이는 DDL과 간단한 SQL 문에 유용합니다. 대량 삽입이나 쿼리를 반복 처리하는 용도로는 사용하지 않는 것이 좋습니다.
배치 삽입
대량의 행을 삽입할 수 있도록 클라이언트는 배치 처리 semantics를 제공합니다. 이를 위해 먼저 행을 추가할 수 있는 배치를 준비해야 합니다. 준비된 배치는 마지막에Send() 메서드로 전송됩니다. 배치는 Send가 실행될 때까지 메모리에 유지됩니다.
연결 누수를 방지하려면 배치에 대해 Close를 호출하는 것이 좋습니다. 이는 배치를 준비한 직후 defer 키워드를 사용해 처리할 수 있습니다. 이렇게 하면 Send가 호출되지 않더라도 연결이 정리됩니다. 단, 행이 하나도 추가되지 않았다면 쿼리 로그에는 0개의 행이 삽입된 것으로 표시됩니다.
임시 컬럼
임시 컬럼은 삽입 시에만 존재하는 쓰기 전용 컬럼으로, 저장되지 않으며 조회할 수도 없습니다. 삽입 시점에 파생 컬럼 값을 계산하는 데 유용합니다.행 조회
QueryRow 메서드를 사용해 단일 행을 쿼리하거나, Query를 통해 결과 집합을 순회할 수 있는 커서를 얻을 수 있습니다. 전자는 데이터를 직렬화해 저장할 대상을 받지만, 후자는 각 행마다 Scan을 호출해야 합니다.
SELECT 문에 지정된 순서대로 전달해야 하며, 위와 같은 SELECT *의 경우 기본적으로 컬럼 선언 순서가 사용됩니다.
삽입과 마찬가지로 Scan 메서드도 대상 변수가 적절한 타입이어야 합니다. 이 역시 가능한 경우 타입 변환이 이루어지도록 유연하게 설계되어 있으며, 정밀도 손실이 없을 때만 변환됩니다. 예를 들어 위 예시에서는 UUID 컬럼을 string 변수로 읽어옵니다. 각 컬럼 타입에 대해 지원되는 Go 타입의 전체 목록은 타입 변환을 참조하십시오.
마지막으로, Query 및 QueryRow 메서드에 Context를 전달할 수 있다는 점에도 유의하십시오. 이는 쿼리 수준 설정에 사용할 수 있습니다. 자세한 내용은 Using Context를 참조하십시오.
비동기 삽입
비동기 삽입은 Async 메서드를 통해 사용할 수 있습니다. 이를 사용하면 클라이언트가 서버에서 삽입을 완료할 때까지 기다릴지, 아니면 데이터가 수신되는 즉시 응답할지를 지정할 수 있습니다. 즉, wait_for_async_insert 매개변수를 제어합니다.열 지향 삽입
삽입은 열 포맷으로 수행할 수 있습니다. 데이터가 이미 이런 구조로 되어 있다면 행으로 피벗할 필요가 없어져 성능상 이점을 얻을 수 있습니다.구조체 사용하기
Golang 구조체는 사용자에게 ClickHouse의 데이터 행(row)을 논리적으로 표현하는 방법을 제공합니다. 이를 위해 네이티브 인터페이스는 몇 가지 편리한 함수를 제공합니다.serialize와 함께 사용하는 Select
Select 메서드를 사용하면 한 번의 호출로 응답 행 집합을 struct 슬라이스에 마샬링할 수 있습니다.구조체 스캔
ScanStruct를 사용하면 쿼리의 단일 행을 구조체로 마샬링할 수 있습니다.
구조체 추가
AppendStruct를 사용하면 기존 배치에 구조체를 추가할 수 있으며, 이 구조체는 완전한 행으로 해석됩니다. 이때 구조체의 필드는 이름과 유형이 모두 테이블과 일치해야 합니다. 모든 컬럼에는 이에 대응하는 구조체 필드가 있어야 하지만, 일부 구조체 필드에는 대응되는 컬럼이 없을 수 있습니다. 이러한 필드는 무시됩니다.
서버 측 쿼리 매개변수
ClickHouse 서버 측 쿼리 매개변수는{name:Type} 형식의 타입이 지정된 플레이스홀더를 사용합니다. 쿼리와 매개변수 값은 별도로 전송되므로 매개변수 값이 SQL 텍스트에 직접 삽입되지 않습니다.
ClickHouse API에서는 쿼리 Context를 통해 매개변수를 전달하십시오.
clickhouse.Named를 사용하여 값을 전달할 수도 있습니다.
clickhouse.Named는 클라이언트 측 @name 바인딩 구문에서도 사용할 수 있으며, 어떤 방식이 적용될지는 쿼리 내 플레이스홀더({name:Type} 또는 @name)에 따라 결정됩니다.
String 값과 이스케이프 시퀀스
문자열 값이 어떻게 해석되는지는 값을 전달하는 방식에 따라 달라집니다.clickhouse.Named(또는 sql.Named)에 string/*string 또는 []byte/*[]byte 값을 전달하면 Go 값이 리터럴 매개변수 값으로 처리됩니다. 드라이버가 제어 문자를 자동으로 이스케이프하므로, 두 프로토콜 모두에서 값이 바이트 단위까지 그대로 왕복됩니다. 값에 실제 줄바꿈이나 탭 문자가 들어 있어도 문제없습니다.
clickhouse.Parameters / WithParameters**에는 항상 ClickHouse의 Escaped 포맷으로 이미 직렬화된 매개변수 텍스트가 들어갑니다. 자동 이스케이프는 수행되지 않습니다. ClickHouse는 매개변수를 파싱할 때 다음 백슬래시 이스케이프 시퀀스를 디코딩합니다: \n(줄 바꿈), \t(탭), \r(캐리지 리턴), \0(널 바이트), \\(리터럴 백슬래시). \N은 널 허용 타입에서 값 전체가 NULL임을 나타내는 마커입니다.
Go는 해석된 문자열 리터럴("...")을 clickhouse-go에 전달하기 전에 먼저 처리하는 반면, 원시 문자열 리터럴(`...`)은 백슬래시를 그대로 유지합니다. Parameters에 전달할 매개변수 텍스트는 다음과 같이 작성하십시오.
Parameters를 구성할 때는 "line 1\nline 2"나 "column 1\tcolumn 2"를 사용하지 마십시오. 이러한 Go 리터럴에는 이미 실제 줄 바꿈 또는 탭 문자가 들어 있습니다. ClickHouse의 Escaped 포맷에서는 실제 줄 바꿈 및 탭 바이트가 필드 구분자로 사용되므로, 매개변수가 끝까지 파싱되지 않아 서버에서 거부됩니다. Go 문자열을 리터럴 값 그대로 처리하려면 Named를 사용하십시오.
매개변수 값은 SQL 리터럴이 아닙니다. Named로 최상위 String을 전달할 때는 값을 SQL 따옴표로 감싸지 마십시오. 따옴표 문자도 값의 일부가 되므로 'hello'가 아닌 hello를 사용해야 합니다. 복합 타입은 여전히 텍스트 구문을 사용합니다. 예를 들어 Array(String)에는 ['a', 'b']를 사용하며, 텍스트에 백슬래시 이스케이프나 원시 제어 문자가 없다면 Named로도 전달할 수 있습니다. 중첩된 문자열 값에 \' 이스케이프 시퀀스가 필요한 복합 텍스트는 Parameters로 전달하십시오.
전체 네이티브 API 예시
매개변수 바인딩
클라이언트는Exec, Query, QueryRow 메서드에서 매개변수 바인딩을 지원합니다. 아래 예시와 같이 이름 있는 매개변수, 번호 매겨진 매개변수, 위치 매개변수를 사용할 수 있습니다. 각 방식의 예시는 아래에 나와 있습니다.
특수한 경우
기본적으로 슬라이스는 쿼리에 매개변수로 전달되면 쉼표로 구분된 값 목록으로 펼쳐집니다.[ ]로 감싼 값 집합을 주입해야 하는 경우 ArraySet을 사용해야 합니다.
그룹/튜플이 필요하고, 예를 들어 IN 연산자와 함께 사용하기 위해 ( )로 감싸야 하는 경우 GroupSet을 사용할 수 있습니다. 이는 아래 예시와 같이 여러 그룹이 필요한 경우에 특히 유용합니다.
마지막으로, DateTime64 필드는 매개변수가 올바르게 렌더링되도록 하려면 정밀도가 필요합니다. 하지만 필드의 정밀도 수준은 클라이언트가 알 수 없으므로 사용자가 직접 제공해야 합니다. 이를 쉽게 처리할 수 있도록 DateNamed 매개변수를 제공합니다.
Context 사용
Go Context는 API 경계를 넘어 마감 시간, 취소 신호 및 기타 요청 범위 값을 전달하는 수단을 제공합니다. 연결의 모든 메서드는 첫 번째 인수로 Context를 받습니다. 앞선 예시에서는context.Background()를 사용했지만, 이 기능을 사용하면 설정과 마감 시간을 전달하고 쿼리를 취소할 수 있습니다.
withDeadline으로 생성한 Context를 전달하면 쿼리에 실행 시간 제한을 설정할 수 있습니다. 이는 절대 시간을 기준으로 하며, 만료되면 연결만 해제되고 ClickHouse에 취소 신호만 전송된다는 점에 유의하십시오. 또는 WithCancel을 사용해 쿼리를 명시적으로 취소할 수도 있습니다.
도우미 함수 clickhouse.WithQueryID와 clickhouse.WithQuotaKey를 사용하면 쿼리 ID와 쿼터 키를 지정할 수 있습니다. 쿼리 ID는 로그에서 쿼리를 추적하거나 취소할 때 유용합니다. 쿼터 키는 고유한 키 값을 기준으로 ClickHouse 사용량에 제한을 적용하는 데 사용할 수 있습니다. 자세한 내용은 Quotas Management를 참조하십시오.
또한 Context를 사용하면 Connection Settings에 나와 있는 것처럼 연결 전체가 아니라 특정 쿼리에만 설정이 적용되도록 할 수 있습니다.
마지막으로 clickhouse.WithBlockSize를 통해 블록 버퍼 크기를 제어할 수 있습니다. 이는 연결 수준 설정인 BlockBufferSize를 재정의하며, 한 번에 디코딩되어 메모리에 유지되는 블록의 최대 개수를 제어합니다. 값을 크게 하면 메모리 사용량이 늘어나는 대신 더 높은 수준의 병렬 처리가 가능해질 수 있습니다.
위에서 설명한 내용의 예시는 아래와 같습니다.
Progress, profile 및 log 정보
쿼리에 대해 Progress, Profile 및 Log 정보를 요청할 수 있습니다. Progress 정보는 ClickHouse에서 읽고 처리한 행 수와 바이트 수에 대한 통계를 제공합니다. 한편, Profile 정보는 비압축 바이트 수, 행 수, 블록 수를 포함하여 클라이언트에 반환된 데이터의 요약을 제공합니다. 마지막으로, Log 정보는 스레드 관련 통계(예: 메모리 사용량 및 데이터 처리 속도)를 제공합니다. 이 정보를 얻으려면 Context를 사용해야 하며, 여기에 콜백 함수를 전달할 수 있습니다.동적 스캔
반환되는 필드의 스키마나 유형을 알 수 없는 table을 읽어야 할 수 있습니다. 이는 애드혹 데이터 분석을 수행하거나 범용 도구를 작성할 때 흔히 발생합니다. 이를 위해 쿼리 응답에서 컬럼 유형 정보를 제공합니다. 이 정보는 Go 리플렉션과 함께 사용하여 올바른 유형의 변수를 런타임에 생성하고, 이를 Scan에 전달하는 데 사용할 수 있습니다.외부 테이블
외부 테이블을 사용하면 클라이언트가 SELECT 쿼리와 함께 데이터를 ClickHouse로 전송할 수 있습니다. 이 데이터는 임시 테이블에 저장되며, 쿼리 실행 시 쿼리 내에서 사용할 수 있습니다. 쿼리와 함께 외부 데이터를 클라이언트로 보내려면, Context를 통해 전달하기 전에ext.NewTable로 외부 테이블을 생성해야 합니다.
OpenTelemetry
ClickHouse는 TCP와 HTTP 전송 모두에서 추적 컨텍스트 전파를 지원합니다. TCP를 사용할 경우 클라이언트는 스팬을 네이티브 바이너리 프로토콜로 직렬화합니다.clickhouse.WithSpan을 사용해 Context를 통해 쿼리에 스팬을 첨부하세요.
HTTP 전송 제한ClickHouse 서버는 표준
traceparent / tracestate HTTP 헤더를 수신하지만, clickhouse-go의 HTTP 전송은 현재 이를 보내지 않으므로 HTTP에서는 WithSpan이 적용되지 않습니다. 우회 방법으로 연결 옵션의 HttpHeaders를 통해 헤더를 수동으로 설정할 수 있습니다.