하이브에서는 다양한 형식의 파일을 읽고 저장할 수 있도록 테이블 별로 파일 형식을 지정할 수 있습니다.

 

 

하이브(Hive) 파일 형식

하이브에서는 테이블 생성 시 'STORED AS 저장형식명' 옵션을 사용하여 테이블별로 파일 형식을 지정할 수 있습니다. 파일 형식을 그냥 쉽게 표현하자면 하이브에서 테이블 형태로 보여지는 데이��

sparkdia.tistory.com

  하이브에서 기본적으로 제공하는 파일 형식 중에서 현재 가장 많이 사용되는 것이 ORC 파일 형식입니다.

  ORC 파일 형식은 컬럼 기반으로 데이터를 저장하며, 기존의 컬럼 기반 저장 방식을 사용하는 RCFile을 개선한 파일 형식입니다. ( ※ 컬럼 기반 저장 방식은 위 하이브(Hive) 파일 형식 포스트를 참고 바랍니다. )

 

   RCFile과 비교하였을 때 ORC의 장점은 아래와 같습니다.

- 각 태스크의 결과가 하나의 파일로 생성되어 네임노드의 부하가 감소됨.
- Datetime, Decimal, complex types (struct, list, map, and union)등의 하이브 데이터 타입을 지원함.
- 파일에 경량 인덱스가 저장됨.
. 필터링 조건에 부합하지 않는 로우 그룹은 skip함. 
. 특정 row로 바로 탐색이 가능.
- 데이터 타입 기반의 block-mode 압축. 
. Integer 컬럼은 run-length encoding을 사용함.
. String 컬럼은 dictionary encoding을 사용함.
- 하나의 파일을 여러 개의 레코드리더를 사용해 동시 읽기 가능함
- 마커 스캐닝 없이 파일 분할이 가능함.
- 읽거나 쓰기에 필요한 메모리의 용량을 제한 가능함
- 메타 데이터를 Protocol Buffers를 사용해 저장함으로써 필드의 추가/삭제가 가능함.

 

 

파일 구조

  ORC의 파일 구조는 아래와 같습니다.

 

Stripe

  컬럼 기반 저장 방식에서는 저장 시 테이블의 데이터를 우선 수평적으로 분할합니다. 분할 기준은 로우 그룹의 크기입니다. 분할된 각각의 로우 그룹 내 데이터를 컬럼 기준으로 저장하게 됩니다. 

  이렇게 분할된 로우 그룹이 Stripe이며, Index Data, Row Data, Stripe Footer로 구성됩니다.

 

Index data

  Index data에는 각 컬럼의 최솟값, 최댓값과 각 컬럼 내 로우의 위치를 저장하고 있습니다. 

  필터링 조건에 의해 테이블의 일부 데이터만 추출하는 경우, 이 Index data를 참고하여 조건에 맞지 않은 로우 그룹은 skip하고 조건에 맞는 로우 그룹만 액세스하게 됩니다.

 

Row data

  실제 테이블 데이터가 저장되어 있습니다.

 

Stripe footer

  스트림 위치 정보가 저장되어 있습니다.

 

File footer

  File footer에는 아래와 같은 보조 정보가 저장되어 있습니다.

  • 파일 내 stripe의 목록
  • stripe별 로우의 수
  • 각 컬럼의 데이터 타입
  • 컬럼 레벨별 통계 정보(건수, 최솟값, 최댓값, 합계)

 

Postscript

  파일의 가장 끝에 위치하며, 압축된 footer의 크기와 압축 파라미터 정보가 저장됩니다.

 

 

 

Integer 컬럼 직렬화 (Integer Column Serialization)

  ORC에서 Interger 컬럼은 두 개의 스트림, bit stream(해당 값이 not-null인지 표현)과 data stream(integer의 스트림)으로 직렬화(serialize)됩니다.

  Interger 데이터는 아래와 같이 숫자의 특징에 따른 encoding 방식이 적용되어 직렬화됩니다.

  •   interger 값이 작아 데이터의 크기가 경량인 경우 variable-width encoding을 사용.
  •   값이 반복되는 경우 run-length encoding을 사용.
  •   정수 값의 범위가 -128에서 127인 경우 run-length encoding을 사용.

  

Variable-width encoding 

  Variable-width encoding은 Google의 프로토콜 버퍼 기반입니다.

  가변 폭 데이터를 인코딩하므로 각 Integer 값의 byte 크기는 각각 상이할 것입니다. 인코딩되는 데이터의 크기가 서로 다른 값들을 구분하기 위해 각 byte의 최상위 bit를 사용합니다. 각 byte의 최상위 bit는 현재 byte가 인코딩하는 데이터의 마지막 바이트를 나타냅니다. 하위 7bit는 인코딩된 데이터를 나타냅니다.

 

Run-length encoding

  Run-length encoding은 반복되는 문자를 반복회수로 표현하는 압축 방법입니다.

  예를들어, 문자열 'AAAAABBBCCCCCCCCDDDEEEEEEEE'인 경우에 Run-length encoding을 적용하면 '5A3B7C3D8E'로 인코딩 됩니다.

 

 

 

문자열 컬럼 직렬화 (String Column Serialization)

문자열 컬럼은 컬럼의 unique한 값들로 구성된 딕셔너리를 사용하여 직렬화됩니다. 딕서너리 내 값들은 정렬되어 있어 predicate filtering의 속도가 높아지고 압축률이 향상됩니다.

  문자열 컬럼은 아래 4개의 스트림으로 직렬화됩니다. 

  •   bit stream : 값이 not-null인지 표현
  •   dictionary data : 문자열의 크기(byte)
  •   dictionary length : 각 항목의 길이
  •   row data : 로우의 값 

 

 

압축 (Compression)

  ORC 파일 포맷을 사용하는 테이블의 모든 스트림은 지정된 코덱을 사용하여 압축됩니다. 압축 코덱은 테이블 생성 시 TBLPROPERTIES 옵션 내 orc.compress라는 key 값을 정의하여 지정 가능합니다. 코덱은 ZLIB, SNAPPY을 사용하거나 none을 선택할 수 있습니다.

  아래 Hortonworks(현재는 Cloudera로 흡수되었죠.)에서 성능 테스트를 한 결과를 보면 ORC 파일 형식이 다른 파일 형식에 비해 상당히 높은 압축률을 보여주고 있음을 확인할 수 있니다. 

[출처] https://blog.cloudera.com/orcfile-in-hdp-2-better-compression-better-performance/

 

 

 

[Ref.] https://cwiki.apache.org/confluence/display/Hive/LanguageManual+ORC#LanguageManualORC-HiveQLSyntax

    https://blog.cloudera.com/orcfile-in-hdp-2-better-compression-better-performance/

 

+ Recent posts