Hive 가 자신의 데이터를 소유하는 형태를 말한다.
hive 에대해서 external table 이라는 선언으로 create table 을 하지 않는다면, 기본으로 적용된다.
hive 의 전용 경로 하위에 자동으로 생성된다. location 옵션으로 따로 지정할 수도 있다.
hive의 table 이나 partition을 drop 하면, 해당 경로의 HDFS 파일 또한 지워진다.
선언시 create external table if not exists [external-table-name]...
로 선언한다.
external table 은 원본 데이터를 hive 가 관리하지 않는다.
Hive 의 영역 외에도 테이블을 사용하고 싶을 때 사용한다. ( 거의 모든 경우에 사용한다.)
데이터가 같은 HDFS의 경로 뿐만 아니라 외부의 경로로도 지정할 수 있다.
external table 의 partition이나 table 을 drop 하면, hive 상의 메타데이터에서만 삭제되고 원본데이터에는 변화가 없다.
여러 하둡 클러스터가 Federation(연합) 구조로 운영되는 경우, 하나의 Hive에서 외부 클러스터에 존재하는 데이터를 참조할 수 있다.
예를 들어, 분석 클러스터에서 운영 클러스터의 HDFS 데이터를 external table로 연결하면, 데이터를 복사하지 않고도 운영 데이터를 분석할 수 있다.
WebHDFS는 HTTP REST API를 통해 HDFS에 접근할 수 있는 인터페이스이다.
이를 활용하면, 로컬 클러스터에서 직접 HDFS RPC 연결 없이 원격 HDFS 데이터에 접근할 수 있다.
Hive external table은 이 경로를 테이블의 데이터 소스로 지정할 수 있다.
External table은 데이터를 Hive가 직접 관리하지 않기 때문에 다음과 같은 불편함이 있다.
데이터 로딩 인식 문제
외부 애플리케이션(예: data loader)이 Hive를 거치지 않고 HDFS에 데이터를 저장하면, Hive는 그 사실을 자동으로 알지 못한다. 즉, 데이터 파일이 경로에 존재하더라도 Hive 메타스토어에는 반영되지 않는다.
메타데이터 업데이트 필요
새로운 데이터가 추가되거나 삭제된 경우, 사용자가 Hive에 이를 알려주어야 한다. 보통 ALTER TABLE
명령을 통해 파티션 단위로 메타데이터를 갱신한다.
추가적인 작업 부담
따라서 외부에서 데이터를 적재할 때마다 Hive에 메타데이터 업데이트 명령을 별도로 수행해야 한다. 이 과정을 생략하면 Hive 쿼리에서는 새로운 데이터가 조회되지 않는다.
새롭게 데이터가 추가되거나 삭제된 경우, alter table 로 할 수 있다.
alter table table_name add partition (partition1=x, partition2=2, ..)
alter table table_name drop partition (partition1=x, ...)
또한 msck 로도 한 번에 메타데이터 업데이트가 가능하다.
MSCK [REPAIR] TABLE table_name [ADD/DROP/SYNC PARTITIONS];
해당 hive session 에서만 유지되는 테이블이다.
보통 select 의 결과를 임시테이블로 만들어서, 새로운 쿼리에서 참조할 때 쓰려고 사용한다.
다음 명령어로 internal/external 을 구분할 수 있다.
DESCRIBE FORMATTED table_name;
****show create table table_name;
Hive 를 이용한 아키텍처에서 주로 데이터를 저장하는 쪽은 Hive 를 통하지 않고, 다이렉트로 파일로 쓰는 경우가 많다.
데이터를 쓰기 전에 스키마만 하이브를 통해서 조회하는 식이다. (external table)
즉 Hive가 데이터를 저장하려면 저장하는 쪽에서 어떤 형식으로 저장했는지를 알아야, 테이블 정의 스키마에 맞게 파일을 읽을 수 있다.
따라서 Hive의 테이블 속성에는 무조건 데이터를 어떤 형식으로 다루어야 하는지 정보가 필요하다.
Hadoop에서 자주 사용하는 데이터 포맷은 공통적으로 다음 특징을 가진다.
일반 프로그래밍을 할 때 자주 사용하는 csv, xml, json 등은 확장 가능한 포맷이 아니다.
row 기반의 바이너리 storage 포맷이다. 데이터의 스키마의 정의는 json 으로 되어있다.
데이터 serialization capacity 가 좋다.
schema evolution 이 가능하고, 유연하다.
serialization capacity
데이터를 메모리 객체에서 바이너리 형태로 변환해 저장하거나 전송하는 능력으로, 용량 효율성과 처리 속도를 의미한다.
Schema evolution
데이터 스키마가 변경되더라도 기존 데이터와의 호환성을 유지하면서 새로운 스키마를 적용할 수 있는 기능이다
big-data에 이상적인 columnar storage 이다.
복잡한 nested data 구조를 표현할 수 있는 columnar 포맷이다.
Nested data structure
Nested Data = 계층적/중첩된 데이터 구조
예를 들어 JSON 같은 구조:{ "user_id": 1, "name": "현준", "orders": [ {"order_id": 101, "price": 20000}, {"order_id": 102, "price": 15000} ] }
여기서
orders
필드는 배열(List)이고, 그 안에 다시 객체(Map/Struct)가 들어있으므로 nested structure라고 부름.
Optimized Row Columnar(ORC) file format을 지향하고, 기본적으로 columnar 의 특징을 갖는다.
ORC 파일은 각 column chunk에 row-level index(최솟값, 최댓값, 위치 정보 등) 를 저장하므로, 필요 없는 데이터를 건너뛰고 원하는 데이터만 빠르게 조회할 수 있어 성능이 뛰어나다.
인덱스 때문에 스키마의 순서가 중요하다.
Columnar의 특징
데이터를 행(row) 단위가 아니라 열(column) 단위로 저장하기 때문에, 특정 컬럼만 조회할 때 불필요한 데이터를 읽지 않아도 되어 조회 성능과 압축 효율이 높다.
예를 들어, 100개의 열 중에서 3개 열만 필요하다면 columnar 포맷은 그 3개 열만 읽으면 되지만, row 기반 포맷은 모든 열을 읽고 필요 없는 데이터를 버려야 한다.
Hadoop은 일반적으로 읽기(조회)를 많이 하는 목적에서 사용된다.
RDBMS 데이터 백업과 같이 메타데이터(유저 정보, 서비스 정보 등)를 Hadoop에 저장하려면 스키마가 필요하다.
반면 집계형 데이터(Analytics 목적)는 스키마가 한 번 정해지면 잘 바뀌지 않는다.
만약 인덱스가 매우 중요하고, 데이터 구조가 거의 바뀌지 않으며, 저장과 조회가 엄격하게 관리되는 환경이라면 ORC
가 더 적합하다.
종합적으로, 성능·유연성·확장성 측면에서 Parquet이 가장 많이 사용된다.
Hadoop은 대용량 데이터를 저장하는 저장소이므로, 이를 대상으로 쿼리를 수행할 때는 partition을 거의 필수적으로 적용하는 것이 좋다.
앞에서 배운 것처럼, partition은 수평적 확장을 가능하게 하는 방식이며, Hive에서 적용하는 partition 역시 사실상 수평적 확장에 해당한다.
Partition을 설정하면, 파티션 필드=값
의 이름으로 디렉토리가 생성된다. (external table인 경우 디렉토리 이름이 이와 같아야 한다.)
Partition의 순서대로 디렉토리 구조가 hierarchy 로 결정된다.
예 1 : PARTITIONED BY year, month, day
table_path
L year=2022
L month=202201
L day=20220101
예 2: PARTITIONED BY day, month, year
table_path
L day=01
L month=0101
L year=20220101
파티션은 hadoop의 디렉토리 구조로 hierarchy 를 가지기 때문에 사실상 위계관계인 데이터 구조를 partition으로 설정해야 한다. (연> 월> 일)
가장 기본으로 연, 월, 일을 기준으로 한다. 서비스에 맞게 추가로 연,월, 일 사이 또는 하위에 추가적인 파티션을 가져가기도 한다.
파티션은 모든 거의 모든 쿼리에 조건으로 들어갈 대상을 지정하는 것이 좋다.
또한 파티션의 물리적인 위치가 hierarchy 가 있는 directory 구조를 따르기 때문에 partition 필드의 순서가 데이터의 위계질서와 맞아야 원하는 성능을 얻을 수 있다.
또한 Hadoop 은 write-once-read-many access model 에 적합하기 때문에 읽을 때 어떻게 읽을 지를 기준으로 파티션을 설정하는 것이 좋다.
create table 시에 column 리스트 다음에 다음과 같이 추가해준다.
partitioned by (col_name data_type, col_name2 data_type2, ..)
Hive table data model의 마지막 레벨이다. (table > partition > bucket)
Bucketing은 partition directory 하위에, 특정 필드(들)가 같은 값들이 하나의 파일로 모이도록 hashing 해서 파일로 만드는 작업을 말한다.
유저는 선언할 때 어떤 컬럼을 기준으로 hash할 것인지, 총 몇 개의 bucket 을 만들 것인지 설정하면 된다.
같은 값을 가진 필드가 같은 파일에 위치하므로, bucketing 한 필드로 필터링을 하면 locality 가 높아진다.
조회하는 조건이 bucket 에서 사용하는 컬럼보다 다양한 경우, bucket의 효용성이 떨어진다. (random access 가 다양한 쿼리에서 성능의 median 은 더 좋을 수 있다.)
확정적으로 얘기할 수 없지만 굳이 할 필요 없는 버켓팅을 할 필요는 없다.
Create table 시에 partitioned by 다음에 다음과 같이 추가한다.
CLUSTERED BY (column1, column2, ...) INTO $number BUCKETS