
이 글은 하이브 완벽 가이드 책을 읽고 그 중 일부 내용을 정리한 글입니다.
하이브는 관계형 데이터베이스에서 볼 수 있는 여러 원시 데이터형 뿐만 아니라 관계형 데이터베이스에서는 거의 볼 수 없는 세 가지 종류의 컬렉션 데이터형을 지원합니다.
따라서 텍스트 파일에서 이런 데이터형을 어떻게 표현할 것이며, 어떤 텍스트 저장 방법을 사용할지가 중요합니다. 하이브의 독특한 기능 중 하나는 파일에 데이터를 저장할 때 다양한 방법으로 인코딩할 수 있는 유연성을 제공한다는 점입니다. 또한 하이브는 다른 데이터베이스와 달리 데이터의 저장과 생명 주기를 사용자가 스스로 제어할 수 있도록 합니다.
원시 데이터형
| 데이터형 | 크기 | 리터럴 문법 예제 |
| TINYINT | 1바이트 크기의 정수 데이터형 | 20 |
| SMALLINT | 2바이트 크기의 정수 데이터형 | 20 |
| INT | 4바이트 크기의 정수 데이터형 | 20 |
| BIGINT | 8바이트 크기의 정수 데이터형 | 20 |
| BOOLEAN | TRUE 또는 FALSE | TRUE |
| FLOAT | 4바이트 크기의 부동소수점 데이터형 | 3.14 |
| DOUBLE | 8바이트 크기의 부동소수점 데이터형 | 3.14 |
| STRING | 문자의 시퀀스 | 'Now is the time' |
| TIMESTAMP | 정수형, 부동수시점, 문자열형 | 1327882394(유닉스 표준 타임스탬프), 1327882394.123456789(나노 초 추가), '2022-09-11 00:00:00.123456789'(JDBC 호환 java.SQL.Timestamp 포맷) |
| BINARY | 바이트의 배열 형태 지원 |
하이브는 다른 SQL에서 일반적으로 지원하는 최대 허용 길이를 갖는 문자 배열(VARCHAR)을 지원하지 않습니다. 하둡, 하이브는 디스크의 읽기, 쓰기 성능 최적화를 강조하기 때문에 컬럼값의 길이를 고정하는 것은 상대적으로 중요하지 않습니다.
TIMESTAMP 데이터형은 UTC 시간으로 해석되됩니다. 하이브에서는 시간대에 따라 각각 변환하는 to_utc_timestamp, from_utc_timestamp를 내장 함수로 제공합니다.
BINARY 데이터형은 RDBMS에서 볼 수 있는 VARBINARY와 비슷하지만 RDBMS와 달리 데이터를 별도의 저장소에 저장하지 않고 레코드에 모두 저장합니다. BINARY 데이터형은 레코드에 임의의 바이트값을 넣어 하이브가 값을 숫자나 문자열 등으로 파싱하는 것을 막을 때 사용할 수 있습니다.
문자열 컬럼의 값을 숫자로 해석하고자 하는 쿼리는 CAST(s AS INT)와 같이 CAST 함수를 사용합니다.
컬렉션 데이터형
하이브는 struct, map, array 컬럼을 지원합니다.
| 데이터형 | 설명 | 리터럴 문법 예제 |
| STRUCT | C 언어의 구조체나 객체와 유사하다. 각가의 필드는 .으로 접근한다. | struct('John', 'Doe') |
| MAP | 키-값 형태의 컬렉션 데이터 형으로, ['key'] 처럼 필드를 배열 표기법으로 접근한다. | map('first':'John', 'last':'Doe') |
| ARRAY | 0으로 시작하는 정수로 인덱싱할 수 있는 동일한 데이터형의 순차 시퀀스이다. | array('John', 'Doe') |
컬렉션 데이터형은 정규화를 깰 수 있기 때문에 대부분의 관계형 데이터베이스에서는 지원하지 않습니다. 그러나 빅데이터 시스템에서 외래 키 관계의 데이터를 탐색하는 것은 상당한 성능 오버 헤드를 유발하므로 하이브에서는 지원합니다.
컬렉션 데이터형은 자바의 Generic 문법 규칙을 따르는 것을 유의해야 합니다. 예를 들어 MAP<STRING, FLOAT>의 모든 키는 STRING 데이터형을 가지고 모든 값은 FLOAT 데이터형을 가집니다. ARRAY<STRING>도 마찬가지로 모든 아이템은 STRING 데이터형을 가집니다. STRUCT는 서로 다른 데이터형을 섞어서 사용할 수 있으나 STRUCT 안에서 선언된 위치는 고정됩니다.
아래는 예제입니다.
CREATE TABLE employees (
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING, FLOAT>
address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>);
데이터 값의 텍스트 파일 인코딩
하이브는 csv, tsv와 같이 일반적인 형식을 가진 텍스트 파일 인코딩을 지원합니다. 그러나 이 두 가지 포맷은 데이터 필드 값에 쉼표 또는 탭이 있을 때 원하는대로 작동하지 않을 수 있다는 주의점이 있습니다. 이런 이유로 하이브는 문자열의 값으로 잘 사용하지 않는 여러 제어 문자를 기본 구분 기호로 사용합니다.
| 구분 기호 | 설명 |
| \n | 텍스트 파일에서 각 줄은 하나의 레코드가 된다. |
| ^A | 모든 컬럼을 분리한다. CREATE TABLE문에서 명시적으로 지정할 때는 8진수 코드 '\001'을 사용한다. |
| ^B | ARRAY, STRUCT 또는 MAP의 키-값 쌍의 요소를 분리한다. CREATE TABLE문에서 명시적으로 지정할 때는 8진수 코드 '\002'를 사용한다. |
| ^C | MAP의 키-값 쌍에서 키를 관련된 값과 분리한다. CREATE TABLE문에서 명시적으로 지정할 때는 8진수 코드 '\003'을 사용한다. |
위 표의 구분자를 명시적으로 지정하여 테이블 선언을 다시하면 아래와 같습니다.
CREATE TABLE employees (
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING, FLOAT>
address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
만약 데이터가 쉼표로 구분된 필드를 가지고 있는 테이블, 즉 csv 파일을 저장 형식으로 사용하는 테이블을 정의하는 예는 다음과 같습니다. 필드를 탭으로 구분하고 싶다면 ',' 대신 '\t'를 사용합니다.
CREATE TABLE employees (
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING, FLOAT>
address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';
Schema on Read
전통 데이터베이스에서 외부 데이터 로딩, 쿼리 결과물 혹은 UPDATE문 수행을 통하여 데이터를 쓸 때 데이터베이스는 데이터 저장소 모두를 제어합니다. 즉, 데이터베이스가 데이터를 쓸 때 스키마를 강제로 맞추려고 하며 이를 'Schema on Write'라고 합니다.
그러나 하이브는 저장소에 대해 그런 쓰기 제어를 가지고 있지 않습니다. 하이브는 단지 쿼리 결과를 읽어 들일 때만 스키마를 적용하며 이는 'Schma on Read'라고 부릅니다.
만약 스키마와 파일의 내용이 일치하지 않는다면 하이브는 일치하지 않는 필드에 대해 null값을 반환합니다.
'Hadoop Ecosystem > Hive' 카테고리의 다른 글
| [하이브 완벽 가이드] Ch8. HiveQL : 색인(Index) (0) | 2022.10.04 |
|---|---|
| [하이브 완벽 가이드] Ch6. HiveQL : 쿼리 (0) | 2022.09.19 |
| [하이브 완벽 가이드] Ch5. HiveQL : 데이터 조작(DML) (0) | 2022.09.16 |
| [하이브 완벽 가이드] Ch4. HiveQL : 데이터 정의(DDL) (0) | 2022.09.12 |
| [하이브 완벽 가이드] Ch2. 시작하기 (0) | 2022.09.05 |