하둡 완벽 가이드 - 13. PARQUET
본문 바로가기


Programmer/hadoop

하둡 완벽 가이드 - 13. PARQUET

사용자의 입장으로만 하둡을 바라보게 되어 깊이가 부족하다는 생각을 하게 되었다.
하둡 완벽 가이드를 읽고 이해한대로 정리한다.


아파치 파케이는 중첩된 데이터를 효율적으로 저장할 수 있는 컬럼 기준 저장 포맷이다.
컬럼 기준 저장 포맷은 파일 크기와 쿼리 성능 측면 모두에서 효율성이 높은 장점이 있다. (동일한 컬럼의 값을 나란히 모아서 저장하기 때문에 인코딩 효율이 높다.)

파케이의 가장 큰 장점은 진정한 컬럼 기반 방식으로 중첩 구조의 데이터를 저장할 수 있다는 것이다. 중첩된 필드를 다른 필드와 상관없이 독립적으로 읽을 수 있어 상당한 성능 향상을 얻을 수 있었다.

또 다른 특징은 파케이 포맷을 지원하는 수많은 도구가 있다. 프로젝트를 언어 중립 방식으로 파일 포맷을 정의하는 명세 부분과 다양한 언어로 파케이 파일을 읽거나 쓰는 도구를 쉽게 만들 수 있는 명세의 구현체 부분으로 나누었기 때문이다. 맵리튜스, 피그, 하이브, 캐스케이딩, 크런치, 스파크는 대부분 파케이 포맷을 지원한다. 또한 인메모리 표현까지 확장된다. 자바 구현체는 단일 표현에 얽매이지 않기 떄문에 파케이 파일에서 데이터를 읽고 쓰는데 에이브로, 쓰리프트, 프로토콜 버퍼의 인메모리 데이터 모델을 사용할 수 있다.

 

13.1 데이터 모델

파케이의 기본 자료형은 다음과 같다. 

타입 설명
boolean 바이너리 값
int32 부호 있는 32비트 정수
int64 부호 있는 64비트 정수
int96 부호 있는 96비트 정수
float 단정밀도(32비트) IEEE 754 부동소수점 숫자
double 배정밀도(64비트) IEEE 754 부동소수점 숫자
binary 순차 8비트 부호 없는 바이트
fixed_len_byte_array 고정길이 8비트 부호 없는 바이트

파케이 파일에 저장된 데이터는 루트에 필드 그룹을 포함한 message를 갖는 스키마로 정의된다. 각 필드는 반복자 (required, optional, repeated), 타입, 이름으로 되어있다.

message WeatherRecord {
  required int32 year;
  required int32 tmeperature;
  required binary stationId (UTF8);
}

파케이는 기본 자료형에 대한 해석 방식을 정의한 논리 자료형을 제공한다. 따라서 직렬화 표현(기본 자료형)과 애플리케이션에 특화된 시맨틱(논리 자료형)은 차이가 있다.

논리 자료형 어노테이션 설명 스키마 예제
UTF8 UTF-8 캐릭터 문자열.
표기: binary
required binary a (UTF8);
ENUM 명명된 값의 집합
표기: binary
required binary a (ENUM);
DECIMAL(precision, scale) 부호 있는 임의 정밀도 십진수
표기: int32, int64, binary, fixed_len_byte_array
required int32 a (DECIMAL(5,2));
DATE 시간 값이 없는 날짜
표기: int32, 1970년 1월1일(Unix epoch) 이후의 일수로 표현
required int32 a (DATE);
LIST 순서 있는 값의 집합
표기: group
required group a (LIST) {
  repeated group list {
    required int32 element;
  }
}
MAP 순서 없는 키-값 쌍의 집합
표기 group
required group a (MAP) {
  repeated group key_value {
    required binary key (UTF8);
    optional int32 value;
  }
}

 

13.1.1 중첩 인코딩

파케이는 스키마의 모든 기본 자료형 필드의 값을 별도의 컬럼에 저장하고, 그 구조는 명세 수준과 반복 수준의 두 정수로 인코딩한다. 단층 레코드는 null을 사용하고, 중첩이나 반복 수준이 올라가면 null이 아닌 값을 사용해서 비트 필드를 인코딩하는 일반적인 기법으로 명세 수준과 반복 수준을 저장한다.

이 방식을 이용해 중첩 컬럼을 포함한 어떤 컬럼도 다른 컬럼과 상관없이 읽을 수 있다.

13.2 파케이 파일 포맷

파케이 파일은 헤더, 하나 이상의 블록, 꼬리말 순으로 구성된다.

* 헤더: 파케이 포맷의 파일임을 알려주는 4바이트 매직숫자인 PAR1만 포함
* 꼬리말: 파일의 모든 메타데이터가 저장된다. 포맷 버전, 스키마, 추가 키-값 쌍, 파일의 모든 불록에 대한 메타 데이터와 같은 정보를 포함하고 있다. 꼬리말의 마지막 두 필드는 꼬리말 메타데이터의 길이를 인코딩한 4바이트 필드와 매직 숫자인 PAR1이다. 따라서 헤더의 싱크 마커가 필요 없다.
* 블록: 행 그룹을 저장한다. 행 그룹은 행에 대한 컬럼 데이터를 포함한 컬럼 청크로 되어 있다. 각 컬럼 청크의 데이터는 페이지에 기록된다. 각 페이지는 동일한 컬럼의 값만 포함하고 있어 페이지에 있는 값은 비슷한 경향이 있으므로 페이지를 압축할 때 유리하다.

파케이는 파일을 기록할 때 컬럼의 자료형을 기준으로 적합한 인코딩을 자동으로 선택한다. boolean은 연속길이 인코딩과 비트 패킹의 조합으로 기록하고 그 외의 대부분의 자료형은 사전 인코딩을 주로 이용한다. 하지만 사전이 지나치게 커지면 일반 인코딩으로 대체된다. 한 페이지에 사전이 모두 들어가야 하기 때문이다. 이 인코딩 방식은 꼬릿말에 반드시 저장된다.

압축의 두번째 단계는 인코드된 페이지 바이트에 표준 압축 알고리즘을 추가로 적용하는 것이다. 기본적으로 압축하지 않지만 snappy, gzip, LZO 압축 모두 지원한다.

13.3 파케이 설정

파케이 파일의 속성은 파일 기록 시점에 정해진다.

속성명 타입 기본값 설명
parquet.block.size int 128MB 블록의 바이트 크기(행 그룹)
크면 순차 I/O의 성능을 높힐 수 있지만 너무 크면 메모리보다 넘칠 수 있다. 하나의 HDFS 블록(그리고 하나의 데이터노드)에서 읽을 수 있어야 하는 사이즈여야 한다.
parquet.page.size int 1MB 페이지의 바이트 크기
작으면 검색에 효율적이지만 필요한 페이지의 수가 늘어나 저장 용량과 처리 시간이 증가한다.
parquet.dictionary.page.size int 1MB 일반 인코딩으로 돌아가기 전의 사전의 최대 허용 바이트 크기
parquet.enable.dictionary boolean true 사전 인코딩 사용 여부
parquet.compression string UNCOMPRESSED 파케이 파일에서 사용할 압축 종류(UNCOMPRESSED, SNAPPY, GZIP, LZO)

 

13.4 파케이 파일 쓰기와 읽기

파케이 파일은 대부분 피그, 하이브, 임팔라와 같은 고수준 도구를 이용하여 처리한다. 그러나 가끔 저수준 순차 접근이 필요하다.

파케이에는 pluggable 인메모리 데이터 모델이 있다. 자바는 ReadSupport와 WriteSupport로 파케이 파일 포맷을 통합한다.

에이브로, 프로토콜 버퍼, 쓰리프트와 같은 프레임워크로 모델을 정의할 수 있다.

마지막으로, 프로젝션 스키마를 사용해서 파일에 있는 일부 컬럼만 읽는 것도 가능하다.

13.5 파케이 맵리듀스

파케이는 맵리듀스 잡에서 파케이 파일을 읽고 쓰기 위한 맵리듀스 입력과 출력 포맷을 제공하며 에이브로, 프로토콜 버퍼, 쓰리프트 스키마 및 데이터도 사용할 수 있다.