Parquet 형식

Parquet 형식

Parquet 형식은 Hadoop 생태계에서 널리 사용되는 Apache Parquet 컬럼형 저장 형식이에요. ClickHouse는 이 형식의 읽기와 쓰기를 지원합니다. Parquet 데이터 타입과 ClickHouse 데이터 타입 간의 매핑을 지원하며, GeoParquet 사양에 따른 geometry 컬럼 읽기·쓰기도 지원합니다.

출처: 문서

본문

Input Output Alias

설명 (Description)

Apache Parquet은 Hadoop 생태계에서 널리 퍼진 컬럼형 저장 형식입니다. ClickHouse는 이 형식의 읽기와 쓰기 연산을 지원합니다.

데이터 타입 매칭 (Data types matching)

아래 표는 Parquet 데이터 타입이 ClickHouse 데이터 타입과 어떻게 일치하는지 보여줍니다.

Parquet type (logical, converted, or physical) ClickHouse data type
BOOLEAN Bool
UINT_8 UInt8
INT_8 Int8
UINT_16 UInt16
INT_16 Int16 / Enum16
UINT_32 UInt32
INT_32 Int32
UINT_64 UInt64
INT_64 Int64
DATE Date32
TIMESTAMP DateTime64
TIME Time64
FLOAT Float32
DOUBLE Float64
INT96 DateTime64(9, ‘UTC’)
BYTE_ARRAY , UTF8 , ENUM , BSON String
JSON JSON
FIXED_LEN_BYTE_ARRAY FixedString
DECIMAL Decimal
LIST Array
MAP Map
struct Tuple
FLOAT16 Float32
UUID FixedString(16)
INTERVAL FixedString(12)
Point (GeoParquet) Point
MultiPoint (GeoParquet) MultiPoint
LineString (GeoParquet) LineString
Polygon (GeoParquet) Polygon
MultiLineString (GeoParquet) MultiLineString
MultiPolygon (GeoParquet) MultiPolygon
mixed/unknown geometry (GeoParquet) Geometry

Parquet 파일을 쓸 때 일치하는 Parquet 타입이 없는 데이터 타입은 가장 가까운 사용 가능한 타입으로 변환됩니다:

ClickHouse data type Parquet type
IPv4 UINT_32
IPv6 FIXED_LEN_BYTE_ARRAY (16 bytes)
Date (16 bits) DATE (32 bits)
DateTime (32 bits, seconds) TIMESTAMP (64 bits, milliseconds)
Int128/UInt128/Int256/UInt256 FIXED_LEN_BYTE_ARRAY (16/32 bytes, little-endian)
Point BYTE_ARRAY (WKB) + GeoParquet metadata
MultiPoint BYTE_ARRAY (WKB) + GeoParquet metadata
LineString BYTE_ARRAY (WKB) + GeoParquet metadata
Polygon BYTE_ARRAY (WKB) + GeoParquet metadata
MultiLineString BYTE_ARRAY (WKB) + GeoParquet metadata
MultiPolygon BYTE_ARRAY (WKB) + GeoParquet metadata

배열은 중첩될 수 있고 인자로 Nullable 타입의 값을 가질 수 있어요. Tuple과 Map 타입도 중첩될 수 있습니다.

넓은 정수 (Wide integers)

기본적으로 ClickHouse는 Int128, UInt128, Int256, UInt256을 little-endian 순서의 주석 없는 FIXED_LEN_BYTE_ARRAY(16/32) 값으로 기록합니다. 이 레거시 표현은 파일을 이전 ClickHouse 버전에서 읽을 수 있도록 기본값으로 유지됩니다.

대신 표준 Parquet DECIMAL 표현을 사용하려면 output_format_parquet_wide_integer_as_decimal = 1로 설정하세요:

ClickHouse type Parquet logical type Physical type Value encoding
UInt128 DECIMAL(39, 0) FIXED_LEN_BYTE_ARRAY(17) 0 부호 바이트 다음에 16바이트 부호 없는 값을 big-endian 순서로
UInt256 DECIMAL(78, 0) FIXED_LEN_BYTE_ARRAY(33) 0 부호 바이트 다음에 32바이트 부호 없는 값을 big-endian 순서로
Int128 DECIMAL(39, 0) FIXED_LEN_BYTE_ARRAY(17) 16바이트 2의 보수 값을 big-endian 순서로, 17바이트로 부호 확장
Int256 DECIMAL(77, 0) FIXED_LEN_BYTE_ARRAY(33) 32바이트 2의 보수 값을 big-endian 순서로, 33바이트로 부호 확장

소수 표현은 표준 Parquet 컬럼 청크 통계와 페이지 인덱스에 숫자 순서를 제공하므로, ClickHouse가 row-group과 페이지 min/max 프루닝을 사용할 수 있습니다. ClickHouse는 두 인코딩을 모두 읽습니다. 소수 정밀도 39의 경우 스키마 추론은 Decimal256을 기반으로 하는 Decimal(39, 0)을 반환합니다. 명시적 Int128 또는 UInt128 구조를 지정하여 넓은 정수 타입을 복구할 수 있어요. 소수 정밀도 77 또는 78은 ClickHouse Decimal256의 범위를 초과하므로 해당 파일을 읽으려면 명시적 호환 Int256 또는 UInt256 구조가 필요합니다. 명시적 넓은 정수 구조로 ClickHouse는 BYTE_ARRAY 또는 FIXED_LEN_BYTE_ARRAY로 저장된 모든 유효한 너비의 표준 소수 값을 허용하고, 부호 확장을 제거한 후 각 값을 범위 검사합니다.

일부 Parquet 클라이언트는 소수 정밀도 최대 38까지만 지원하고, Arrow의 고수준 소수 타입은 최대 76까지만 지원합니다. 그러한 클라이언트는 스키마와 33바이트 물리적 너비가 Parquet을 따르더라도 정밀도 77/78 표현을 거부할 수 있어요. 더 작은 소수 한계를 가진 구형 ClickHouse 버전이나 클라이언트로 파일을 읽어야 할 때는 설정을 비활성화 상태로 유지하세요.

ClickHouse 테이블 컬럼의 데이터 타입은 삽입되는 Parquet 데이터의 해당 필드와 다를 수 있어요. 데이터를 삽입할 때 ClickHouse는 위 표에 따라 데이터 타입을 해석한 다음 ClickHouse 테이블 컬럼에 설정된 데이터 타입으로 캐스팅합니다. 예를 들어 UINT_32 Parquet 컬럼을 IPv4 ClickHouse 컬럼으로 읽을 수 있습니다.

일부 Parquet 타입에는 밀접하게 일치하는 ClickHouse 타입이 없습니다. 우리는 그것들을 다음과 같이 읽습니다:

  • isAdjustedToUTC=falseTIMESTAMP는 로컬 벽시계 시간입니다(어떤 특정 시간대가 로컬로 간주되는지와 무관하게 로컬 시간대의 연, 월, 일, 시, 분, 초 및 서브초 필드). SQL TIMESTAMP WITHOUT TIME ZONE과 동일합니다. ClickHouse는 그것을 UTC 타임스탬프인 것처럼 읽습니다. 예: 2025-09-29 18:42:13.000(로컬 벽시계 판독값을 나타냄)은 2025-09-29 18:42:13.000(DateTime64(3, 'UTC')는 시점을 나타냄)이 됩니다. String으로 변환하면 올바른 연, 월, 일, 시, 분, 초 및 서브초를 표시하며, 이는 UTC 대신 일부 로컬 시간대에 있는 것으로 해석될 수 있습니다. 직관에 반하여, 타입을 DateTime64(3, 'UTC')에서 DateTime64(3)으로 변경해도 도움이 되지 않습니다. 두 타입 모두 시계 판독값이 아닌 시점을 나타내지만 DateTime64(3)은 로컬 시간대를 사용하여 잘못 형식화될 것이기 때문입니다.
  • INTERVAL은 현재 Parquet 파일에 인코딩된 시간 간격의 원시 바이너리 표현으로 FixedString(12)로 읽힙니다.

Geo 타입 (Geo types, GeoParquet)

ClickHouse는 GeoParquet 사양에 따른 geometry 컬럼의 읽기와 쓰기를 지원합니다. Geometry 컬럼은 WKB(읽을 때는 WKT)로 인코딩된 BYTE_ARRAY 페이로드로 저장되며, 각 geometry 컬럼의 인코딩, geometry 타입, CRS를 설명하는 JSON geo 키가 파일 수준 Parquet 메타데이터에 있습니다.

읽기 동작 (Read behavior)

읽을 때 geometry 컬럼은 해당 ClickHouse geo 데이터 타입으로 매핑됩니다:

  • Point, MultiPoint, LineString, Polygon, MultiLineString 또는 MultiPolygon으로 선언된 컬럼은 일치하는 ClickHouse geo 타입으로 읽힙니다.
  • 여러 개 또는 알 수 없는 geometry 타입을 가진 컬럼은 Geometry 타입으로 읽히며, 이는 모든 지원 geo 타입에 대한 Variant입니다.
  • 요청된 컬럼 타입이 String이면 GeoParquet 메타데이터는 무시되고 원시 인코딩된 geometry 페이로드가 그대로 반환됩니다 — GeoParquet 컬럼이 선언하는 인코딩에 따라 WKB 또는 WKT 바이트. input_format_parquet_allow_geoparquet_parser 설정이 0으로 설정된 경우에도 마찬가지입니다.

쓰기 동작 (Write behavior)

쓸 때 Point, MultiPoint, LineString, Polygon, MultiLineString, MultiPolygon 타입의 최상위 컬럼은 BYTE_ARRAY(WKB)로 인코딩되고 적절한 geo JSON 메타데이터가 Parquet 파일 푸터에 추가됩니다. 최상위 Geometry Variant도 WKB BYTE_ARRAY 페이로드로 인코딩되지만(하위 값은 WKB로 변환되어 Nullable(String) 컬럼으로 저장됨) geo 메타데이터는 출력되지 않아서, 읽을 때 GeoParquet geometry 컬럼으로 인식되지 않습니다. Ring과 같은 다른 geo 관련 타입은 GeoParquet 메타데이터 없이 네이티브 기본 표현으로 기록됩니다. 이 동작은 output_format_parquet_geometadata를 0으로 설정하면 완전히 비활성화할 수 있으며, 이 경우 지원되는 geo 타입조차 네이티브 기본 표현(Point는 Tuple(Float64, Float64), LineString은 Array(Point), Polygon은 Array(Array(Point)) 등)으로 기록되고 GeoParquet 메타데이터는 출력되지 않습니다.

Geometry 컬럼은 스키마의 루트 또는 Tuple(struct) 내부에 중첩되어야 합니다. Array 또는 Map 내부에 중첩하는 것은 지원되지 않습니다. geo 컬럼에는 Nullable도 지원되지 않습니다.

사용 예시 (Example usage)

데이터 삽입 (Inserting data)

football.parquet라는 이름의 Parquet 파일에 다음 데이터가 있다고 가정해 볼게요:

    ┌───────date─┬─season─┬─home_team─────────────┬─away_team───────────┬─home_team_goals─┬─away_team_goals─┐
 1. │ 2022-04-30 │   2021 │ Sutton United         │ Bradford City       │               1 │               4 │
 2. │ 2022-04-30 │   2021 │ Swindon Town          │ Barrow              │               2 │               1 │
 3. │ 2022-04-30 │   2021 │ Tranmere Rovers       │ Oldham Athletic     │               2 │               0 │
 4. │ 2022-05-02 │   2021 │ Port Vale             │ Newport County      │               1 │               2 │
 5. │ 2022-05-02 │   2021 │ Salford City          │ Mansfield Town      │               2 │               2 │
 6. │ 2022-05-07 │   2021 │ Barrow                │ Northampton Town    │               1 │               3 │
 7. │ 2022-05-07 │   2021 │ Bradford City         │ Carlisle United     │               2 │               0 │
 8. │ 2022-05-07 │   2021 │ Bristol Rovers        │ Scunthorpe United   │               7 │               0 │
 9. │ 2022-05-07 │   2021 │ Exeter City           │ Port Vale           │               0 │               1 │
10. │ 2022-05-07 │   2021 │ Harrogate Town A.F.C. │ Sutton United       │               0 │               2 │
11. │ 2022-05-07 │   2021 │ Hartlepool United     │ Colchester United   │               0 │               2 │
12. │ 2022-05-07 │   2021 │ Leyton Orient         │ Tranmere Rovers     │               0 │               1 │
13. │ 2022-05-07 │   2021 │ Mansfield Town        │ Forest Green Rovers │               2 │               2 │
14. │ 2022-05-07 │   2021 │ Newport County        │ Rochdale            │               0 │               2 │
15. │ 2022-05-07 │   2021 │ Oldham Athletic       │ Crawley Town        │               3 │               3 │
16. │ 2022-05-07 │   2021 │ Stevenage Borough     │ Salford City        │               4 │               2 │
17. │ 2022-05-07 │   2021 │ Walsall               │ Swindon Town        │               0 │               3 │
    └────────────┴────────┴───────────────────────┴─────────────────────┴─────────────────┴─────────────────┘

데이터를 삽입합니다:

INSERT INTO football FROM INFILE 'football.parquet' FORMAT Parquet;

데이터 읽기 (Reading data)

Parquet 형식을 사용하여 데이터를 읽습니다:

SELECT *
FROM football
INTO OUTFILE 'football.parquet'
FORMAT Parquet

Parquet는 터미널에서 사람이 읽을 수 있는 형태로 표시되지 않는 바이너리 형식입니다. Parquet 파일을 출력하려면 INTO OUTFILE을 사용하세요. Hadoop과 데이터를 교환하려면 HDFS 테이블 엔진을 사용할 수 있어요.

형식 설정 (Format settings)

Setting Description Default
input_format_parquet_case_insensitive_column_matching Parquet 컬럼을 CH 컬럼과 매칭할 때 대소문자 무시. 0
input_format_parquet_preserve_order Parquet 파일을 읽을 때 행 재정렬 방지. 일반적으로 훨씬 느림. 0
input_format_parquet_filter_push_down Parquet 파일을 읽을 때 WHERE/PREWHERE 표현식과 Parquet 메타데이터의 min/max 통계를 기반으로 전체 row group 건너뛰기. 1
input_format_parquet_bloom_filter_push_down Parquet 파일을 읽을 때 WHERE 표현식과 Parquet 메타데이터의 bloom filter를 기반으로 전체 row group 건너뛰기. 0
input_format_parquet_dictionary_filter_push_down Parquet 파일을 읽을 때(reader v3 사용) WHERE/PREWHERE 표현식과 딕셔너리 페이지 내용을 기반으로 컬럼 청크의 모든 데이터 페이지가 딕셔너리 인코딩된 경우 동등 및 IN 조건에 대해 전체 row group 건너뛰기. 값은 이 최적화가 적용되는 최대 딕셔너리 페이지 크기(바이트). 0으로 설정하면 비활성화. 둘 다 사용 가능할 때 bloom filter보다 우선. 1048576
input_format_parquet_allow_missing_columns Parquet 입력 형식을 읽을 때 누락된 컬럼 허용 1
input_format_parquet_local_file_min_bytes_for_seek Parquet 입력 형식에서 무시하며 읽는 대신 seek을 수행하기 위해 로컬 읽기(파일)에 필요한 최소 바이트 8192
input_format_parquet_enable_row_group_prefetch parquet 파싱 중 row group 프리페치 활성화. 현재 단일 스레드 파싱만 프리페치 가능. 1
input_format_parquet_skip_columns_with_unsupported_types_in_schema_inference Parquet 형식의 스키마 추론 중 지원되지 않는 타입의 컬럼 건너뛰기 0
input_format_parquet_max_block_size parquet 리더의 최대 블록 크기. 65409
input_format_parquet_prefer_block_bytes parquet 리더가 출력하는 평균 블록 바이트 16744704
input_format_parquet_enable_json_parsing Parquet 파일을 읽을 때 JSON 컬럼을 ClickHouse JSON Column으로 파싱. 1
input_format_parquet_allow_geoparquet_parser Parquet 파일을 읽을 때 GeoParquet geo 메타데이터를 인식하고 geometry 컬럼(컬럼의 선언된 인코딩에 따라 WKB 또는 WKT)을 ClickHouse geo 데이터 타입으로 디코딩. 0 이면 geometry 컬럼이 원시 물리적( String ) 표현으로 노출됨. 1
output_format_parquet_row_group_size 행 단위의 대상 row group 크기. 1000000
output_format_parquet_row_group_size_bytes 압축 전 바이트 단위의 대상 row group 크기. 536870912
output_format_parquet_string_as_string String 컬럼에 Binary 대신 Parquet String 타입 사용. 1
output_format_parquet_fixed_string_as_fixed_byte_array FixedString 컬럼에 Binary 대신 Parquet FIXED_LEN_BYTE_ARRAY 타입 사용. 1
output_format_parquet_wide_integer_as_decimal Int128 , UInt128 , Int256 , UInt256 을 레거시 little-endian 고정 바이트 배열 대신 표준 big-endian Parquet DECIMAL 값으로 기록. 0
output_format_parquet_compression_method Parquet 출력 형식의 압축 방법. 지원 코덱: snappy, lz4, brotli, zstd, gzip, none (압축 안 함) zstd
output_format_parquet_parallel_encoding Parquet 인코딩을 여러 스레드로 수행. 1
output_format_parquet_data_page_size 압축 전 바이트 단위의 대상 페이지 크기. 1048576
output_format_parquet_batch_size 이 행 수마다 페이지 크기 확인. 평균 값 크기가 몇 KB를 넘는 컬럼이 있으면 줄이는 것을 고려. 1024
output_format_parquet_write_page_index parquet 파일에 페이지 인덱스 기록 가능성 추가. 1
output_format_parquet_geometadata Parquet 파일 푸터에 GeoParquet geo 메타데이터를 기록하고 최상위 ClickHouse geo 컬럼( Point , MultiPoint , LineString , Polygon , MultiLineString , MultiPolygon )을 WKB로 인코딩. 0 이면 해당 컬럼을 네이티브 기본 표현(예: Point는 Tuple(Float64, Float64) )으로 기록하고 GeoParquet 메타데이터는 출력하지 않음. 1
input_format_parquet_import_nested 더 이상 사용되지 않는 설정, 아무것도 하지 않음. 0
input_format_parquet_local_time_as_utc true isAdjustedToUTC=false인 Parquet 타임스탬프에 대한 스키마 추론에서 사용되는 데이터 타입을 결정. true이면: DateTime64(…, ‘UTC’), false이면: DateTime64(…). ClickHouse에는 로컬 벽시계 시간 데이터 타입이 없으므로 어느 쪽도 완전히 올바르지 않음. 직관에 반하여 ‘true’가 아마 덜 잘못된 선택인데, 그 이유는 ‘UTC’ 타임스탬프를 String으로 형식화하면 올바른 로컬 시간 표현이 생성되기 때문.

더 알아보기 (Learn more)