SELECT 및 INSERT 쿼리를 수행할 수 있습니다. 테이블 구조는 BigQuery 테이블 스키마에서 자동으로 추론됩니다.
읽기에는 BigQuery REST API(tabledata.list)를 사용하므로 네이티브 테이블만 읽을 수 있으며, 뷰, materialized view, 외부 테이블은 읽을 수 없습니다. 쓰기에는 스트리밍 삽입(tabledata.insertAll)을 사용하며, 이를 사용하려면 프로젝트에서 청구를 활성화해야 합니다.
구문
인수
project, dataset, table, access_token 인수는 key = value 형식으로도 지정할 수 있습니다. 위치 인수는 이 순서대로 해당 슬롯을 채우며, 인수를 위치 인수와 키로 모두 지정하거나 동일한 키를 두 번 지정하면 오류가 발생합니다.
다음 인수는 key = value 형식(또는 명명된 컬렉션의 키)으로 지정할 수 있습니다.
인증
- 액세스 토큰. 예를 들어
gcloud auth print-access-token으로 가져올 수 있는 유효한 OAuth 2.0 액세스 토큰입니다. 토큰은 빠르게 만료되며(일반적으로 1시간 후), 이 메서드는 대화형 사용에 가장 적합합니다. - 서비스 계정 키(서버에 권장). Google Cloud IAM에서 생성한 키 파일의 내용을
service_account_key인수로 전달합니다. ClickHouse는 키를 사용해 JWT에 서명하고 이를 액세스 토큰으로 교환하며, 자동으로 갱신합니다. - 갱신 토큰.
client_id,client_secret,refresh_token을 전달합니다. 예를 들어gcloud auth application-default login을 실행한 후~/.config/gcloud/application_default_credentials.json에서 가져올 수 있습니다.
BigQuery 테이블 엔진 또는 CREATE TABLE ... AS bigquery(...) 사용)은 해당 컬렉션의 종속성으로 등록됩니다. 따라서 테이블이 존재하는 동안에는 DROP NAMED COLLECTION이 차단됩니다.
데이터 타입 매핑
참고:
- BigQuery
DATETIME에는 시간대 정보가 없으므로, 표시되는 값이 서버 시간대에 따라 달라지지 않도록DateTime64(6, 'UTC')에 매핑됩니다. NULLABLERECORD는Nullable(Tuple(...))에 매핑되므로 전체 레코드가NULL인 경우 기본값으로 구성된Tuple로 축약되지 않고NULL로 유지됩니다. ClickHouse에서는Array가Nullable내부에 있을 수 없으므로NULL배열(또는 빈 배열)은 빈 배열이 됩니다. BigQuery 배열에는NULL원소를 포함할 수 없으므로(ARRAY<T>는ARRAY<T NOT NULL>과 동일함),REPEATED필드의 원소 타입은Nullable이 아닙니다(Array(T),RECORD원소인 경우Array(Tuple(...))).tabledata.list응답의NULL원소는 잘못된 입력으로 거부됩니다.bigquery테이블 함수를 통해Nullable(Tuple(...))컬럼을 읽고 쓰는 데는 추가 설정이 필요하지 않습니다. 이러한 컬럼을 포함하는 영구BigQuery엔진 테이블을 생성하려면(구조를 추론하든 명시적으로 선언하든) 다른 모든Nullable(Tuple)컬럼과 마찬가지로enable_nullable_tuple_type설정이 필요합니다. 컬럼을 명시적으로 선언할 때는 이 설정을 피하기 위해RECORD필드를 일반Tuple(...)로 선언할 수도 있지만, 이 경우 전체 레코드NULL은 기본 튜플로 강제 변환됩니다. 추론된 타입과 허용되는 유일한 차이는RECORD의Tuple을 감싸는Nullable을 제거하는 것이며, 해당 레코드에서만 가능합니다. 널 허용 여부를 다른 내부 또는 외부 레코드로 옮길 수는 없습니다.GEOGRAPHY는 Geometry에 매핑됩니다. BigQuery는GEOGRAPHY값을 WKT 텍스트로 전송하며, 읽을 때Geometry의 해당 대안(Point,MultiPoint,Ring,LineString,MultiLineString,Polygon,MultiPolygon으로 구성된Variant)으로 파싱되고 쓸 때는 다시 WKT로 직렬화됩니다.GEOMETRYCOLLECTION및 빈 지오메트리(예:POINT EMPTY)에는 대응하는Geometry가 없으므로, 이러한 값이 포함된 행을 읽으면 오류가 발생합니다.Variant는 자체적으로NULL을 저장할 수 있으므로NULLABLEGEOGRAPHY필드는Nullable(Geometry)가 아닌Geometry에 매핑되며,NULL도 왕복 시 보존됩니다.JSON은 JSON 데이터 타입이 아니라String에 매핑됩니다. ClickHouseJSON타입은 최상위 수준에서 객체({...})만 허용하는 반면, BigQueryJSON값은 스칼라, 배열 또는null등 모든 JSON 값이 될 수 있어 이러한 값을 포함한 테이블을 읽을 수 없기 때문입니다. 또한JSON은Nullable로 감쌀 수 없으므로NULLABLE컬럼의 SQLNULL이 보존되지 않습니다.String매핑은 무손실이며, 최상위 객체는CAST(value AS JSON)으로 변환할 수 있습니다.- 정수부가 38자리를 초과하는
BIGNUMERIC값은Decimal(76, 38)에 저장할 수 없으며 오류가 발생합니다. DateTime64/Date32범위(1900-2299년)를 벗어나는TIMESTAMP및DATE값은 지원되지 않습니다.RANGE컬럼은 읽기 전용입니다.tabledata.insertAll은RANGE<T>값을 구조화된{start, end}객체로 기대하지만, 이를String매핑으로부터 재구성할 수 없으므로RANGE컬럼에 삽입하면 오류가 발생합니다.INT64값은tabledata.insertAll에 10진수 문자열로 전송됩니다. API가 JSON 숫자를 double로 파싱하므로, 그렇지 않으면[-2^53 + 1, 2^53 - 1]범위를 벗어나는 값이 손상되기 때문입니다.
예시
gcloud 토큰을 사용하여 공개 데이터셋을 읽습니다:
제한 사항
- 네이티브 BigQuery 테이블만 읽을 수 있습니다. 뷰와 외부 테이블을 읽으려면 BigQuery 쿼리 작업을 실행해야 하지만, 이 함수는 이를 수행하지 않습니다.
RANGE컬럼은String으로 읽을 수 있지만 쓸 수는 없습니다.RANGE컬럼에 삽입하면 오류가 발생합니다.GEOMETRYCOLLECTION이거나 비어 있는 도형인GEOGRAPHY값은Geometry유형으로 표현할 수 없으므로, 이러한 값을 포함한 행을 읽으면 오류가 발생합니다. BigQuery는 이 위치에서NULL을 허용하지 않으므로,REQUIREDGEOGRAPHY필드에NULLGeometry를 쓰거나REPEATEDGEOGRAPHY필드의 요소로 쓰는 작업은 거부됩니다.- 프레디케이트는 푸시다운되지 않습니다.
tabledata.list는 테이블의 행만 나열하며 필터링 매개변수를 제공하지 않습니다(페이지네이션, 컬럼 선택, 포맷 옵션만 지원함). 필터링하려면 BigQuery 쿼리 작업을 실행해야 하지만, 이 함수는 이를 수행하지 않습니다. 따라서WHERE조건은 행을 다운로드한 후 ClickHouse에서 적용됩니다. 전송되는 데이터 양을 줄이려면 컬럼 선택을 사용하십시오. - 반면
LIMIT는 읽는 데이터 양을 줄입니다.maxResults를max_block_size로 설정해 페이지를 지연 요청하며, 쿼리에 필요한 만큼의 행을 확보하면 추가 페이지를 요청하지 않습니다. 단순한LIMIT n의 경우(WHERE,GROUP BY,ORDER BY가 없고n이max_block_size보다 작은 경우) ClickHouse는max_block_size를n으로 낮추므로, 정확히n개 행을 가져오기 위해 정확히 한 번만 요청합니다. 그렇지 않으면 제한을 넘는 첫 페이지 경계에서 읽기가 중단되며, 초과분은 한 페이지 미만입니다. - 명시적인 컬럼 목록을
tabledata.list에 전달하여, 읽기는 쿼리 분석 시점의 스키마에 고정됩니다. 컬럼 목록이 요청 URL 길이 제한을 초과하는 매우 넓은 읽기(예: 수천 개 컬럼이 있는 테이블에서SELECT *)는 고정 없이 읽는 대신 쿼리가 거부됩니다(고정되지 않은 읽기는 동시 스키마 변경으로 인해 정렬이 어긋날 수 있음). 목록이 제한에 맞도록 더 적은 컬럼을 선택하십시오. 동일한 URL 길이 제한은 페이지네이션 요청 전마다 확인됩니다(각 페이지에는 불투명한pageToken이 포함됨). 따라서 이후 페이지가 제한에 맞지 않는 읽기는 중간에 실패하는 대신 동일한 오류와 함께 거부됩니다. - BigQuery 테이블의 스키마를 읽은 뒤 테이블이 변경되면, 일치하지 않는 데이터를 묵묵히 반환하거나 쓰는 대신 쿼리가 거부됩니다. 읽기 직전과
INSERT가 첫 행 스트리밍을 시작하기 전에 라이브 스키마를 다시 가져와 분석된 스키마와 비교합니다. 스키마와 데이터는 별도의 REST 요청으로 가져오므로, 이 확인과 후속 요청 사이에 발생하는 스키마 변경 가능성은 제거할 수 없습니다. - 비교 대상은 쿼리 분석에 사용된 스키마 스냅샷입니다. 이 스냅샷은 테이블 함수가 구조를 확인할 때 생성되며, 영속 테이블(
BigQuery엔진 테이블 또는 동일한 방식으로 컬럼을 유지하는CREATE TABLE ... AS bigquery(...)로 생성된 테이블)의 경우에는CREATE,ATTACH또는 서버 재시작 후 처음 읽거나 쓸 때 생성됩니다. 테이블 메타데이터에는 BigQuery 스키마가 아니라 매핑된 ClickHouse 컬럼이 유지되므로, 테이블이 분리된 상태이거나 서버가 중지된 동안 발생한 스키마 변경은 거부되지 않고 다음 쿼리에서 반영됩니다. 선언된 컬럼은 여전히 라이브 스키마에 대해 검증되고 행은 해당 스키마를 사용해 디코딩되므로, 매핑된 ClickHouse 유형을 유지하는 변경(예:STRING에서BYTES로)은 동일한 컬럼 유형에서 새 유형의 규칙에 따라 읽힙니다. - 스트리밍 삽입으로 기록된 행은 BigQuery 스트리밍 버퍼에 저장되며, 이후 읽기에서 표시되기까지 시간이 걸릴 수 있습니다.
- 대규모
INSERT는 일괄 처리로tabledata.insertAll에 전송됩니다. 요청당 최대 500개 행으로 제한되며, 각 요청이 BigQuery의 10 MB 요청 크기 제한을 넘지 않도록 분할됩니다(이 제한보다 큰 단일 행은 명확한 오류와 함께 거부됨). - 쓰기는 원자적으로 처리되지 않으며, 단일
tabledata.insertAll요청도 일부만 성공할 수 있습니다. BigQuery는 요청에 포함된 일부 행은 커밋하고 나머지 행은insertErrors와 함께 거부할 수 있습니다. 또한 요청은 서로 독립적으로 커밋되므로, 앞선 배치가 수락된 후 후속 배치가 거부될 수 있습니다. 두 경우 모두 쿼리에서 오류가 보고되지만, 이미 커밋된 행은 BigQuery에 그대로 남습니다. 중복을 줄이기 위해 각 행은 쿼리 ID와 스트림에서의 행 순번을 기반으로 생성된 안정적인insertId와 함께 전송됩니다. BigQuery는 이를 사용해 스트리밍 삽입 윈도우 내에서 최선 노력 방식으로 중복을 제거합니다. BigQuery의insertId128자 제한을 초과하는query_id는 고정 길이 접두사로 해시되며, 이 접두사는 해당query_id에 대해 항상 동일하게 유지됩니다.insertId는 행 순번에 따라 달라지므로, 재실행 시 행이 동일한 순서로 생성될 때만 중복 제거를 안정적으로 수행할 수 있습니다. 배치의 전송 수준 재시도는 항상 안전하지만, 동일한query_id로 같은INSERT를 다시 실행할 때는 행이 동일한 순서로 제공되는 경우에만 중복이 제거됩니다(예: 단일 스레드 삽입 또는 그 밖의 결정론적 순서 지정. 시도 간 청크 순서가 달라질 수 있는 병렬INSERT ... SELECT에서는max_threads = 1및max_insert_threads = 1을 설정하십시오).