-
아파치 하이브란? (Apache Hive)Data 2021. 2. 24. 22:21반응형
아파치 하이브는 하둡 환경에서 1) 복잡한 맵리듀스(또는 다른 엔진) 코드를 SQL과 유사한 간단한 HiveQL로 처리가 가능하도록 하고, 2) 파일시스템에 저장된 데이터에 catalog와 metastore를 제공하여 논리적 데이터 베이스, 테이블, 파티션을 제공하여 데이터를 구조화할 수 있게 합니다.
이번글에서는 아파치 하이브의 구조를 중심으로 아래와 같은 내용을 살펴보도록 하겠습니다:
- 하이브의 탄생배경
- 아파치 하이브 아키텍쳐
- 하이브의 데이터모델과 쿼리 (Hive QL)
하이브의 탄생배경
하이브는 페이스북에서 개발이 시작되어, 넷플릭스와 같은 다른 기업도 기여하였습니다. 2000년대 초, 하둡이 탄생하여 데이터 분석은 데이터베이스 기반에서 하둡 환경을 기반으로 진행되기 시작하였습니다. 하둡은 기존의 데이터베이스 환경이 가지고 있던 한계를 넘는 기능을 제공해주었지만 복잡한 맵리듀스 코드를 작성해야 되고, 테이블과 같은 논리적인 개념이 없어서 파일 단위 또는 디렉토리 단위로 데이터를 관리하였습니다.
하이브는 이러한 하둡 환경에서 데이터 웨어하우징과 같은 SQL 기반의 접근을 통한 데이터 처리와 데이터베이스, 테이블, 파티션과 같은 논리적 레벨의 카탈로그 및 메타스토어를 제공합니다.
실례로 아래와 같은 64 라인의 워드카운트 java 맵리듀스 코드는,
package org.myorg; // ... public class WordCount { public static class Map extends Mapper<LongWritable, Text, Text, IntWritable> { // ... } public static class Reduce extends Reducer<Text, IntWritable, Text, IntWritable> { // ... } public static void main(String[] args) throws Exception { Configuration conf = new Configuration(); Job job = new Job(conf, "wordcount"); job.setOutputKeyClass(Text.class); job.setOutputValueClass(IntWritable.class); job.setMapperClass(Map.class); job.setReducerClass(Reduce.class); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); FileInputFormat.addInputPath(job, new Path(args[0])); FileOutputFormat.setOutputPath(job, new Path(args[1])); job.waitForCompletion(true); } }
아래와 같은 하이브 쿼리를 통해 처리될 수 있습니다:
CREATE TABLE docs (line STRING); LOAD DATA INPATH 'docs' OVERWRITE INTO TABLE docs; CREATE TABLE word_counts AS SELECT word, count(1) AS count FROM (SELECT explode(split(line, '\s')) AS word FROM docs) w GROUP BY word ORDER BY word;
아파치 하이브 아키텍쳐
하이브의 아키텍쳐는 아래 이미지와 같이 접근포인트들(CLI, Hive Server, Web UI), 드라이버, 컴파일러, 메타스토어로 구성됩니다:
각 컴포넌트별로 간단하게 살펴보면 [1, 4],
- 접근포인트: CLI, Hive Server, UI와 같은 접근포인트들은 외부 사용자가 하이브에 쿼리를 제출할 수 있는 사용자 인터페이스를 제공합니다.
- Hive Server: 하이브 서버는 하이브 쿼리문을 실행할 수 있는 API를 제공합니다. Thrift는 언어 간의 커뮤니케이션을 위한 프레임웍이기에 Hive Server는 Java로 구현되었지만 다양한 언어를 지원할 수 있습니다.
- 드라이버: 드라이버는 하이브 쿼리를 받고 쿼리의 라이프사이클을 관리하는 컨트롤러 역할을 담당합니다. 세션을 생성하여 쿼리문 실행을 시작하고 진척과 라이프사이클을 모니터링합니다. 또한, 쿼리문 실행 시 생성되는 메타데이터를 저장하고, 리듀스 실행 이후의 결과물을 수집하는 포인트가 됩니다.
- Executor: 컴파일과 최적화 이후에 엑서큐터는 tasks를 실행합니다. 실행 엔진과 연동하여 의존성을 가진 작업이 순차적으로 실행되도록 관리합니다.
- 컴파일러: 하이브 쿼리의 컴파일을 담당하여 쿼리를 실행플랜으로 변환합니다. 이러한 플랜은 결과물을 얻기 위한 실행 엔진의 tasks와 steps를 포함합니다. 컴파일러는 쿼리는 abstract synctax tree(AST)로 변환하고, 호환성과 컴파일 타임 에러 확인 후 DAG(Directed Acyclic Graph)로 다시 변환합니다. DAG은 operators를 실행 엔진의 stages와 tasks로 나누게 됩니다. 또한, 이러한 과정에 논리적, 물리적 플랜을 기초로 최적화를 진행합니다.
- 메타스토어: 각 테이블의 스키마, 위치와 같은 메타데이터를 관리하며 1) data abstraction 과, 2) data discovery 를 제공합니다. 또한, 파티션 메타데이터를 통해서 드라이버가 클러스터에 분산된 다양한 데이터 셋의 progress를 트래킹하도록 돕습니다. 메타스토어는 하이브 메타데이터 쿼리를 위해 Thrift 인터페이스를 제공하며, 드라이버는 MS Client를 통해 메타스토어에 접근합니다.
하이브의 데이터모델과 쿼리 (Hive QL)
하이브의 위의 내부구조는 사용자 입장에서 데이터 처리를 간단하고 명료하게 수행하도록 하는 것을 목표로 합니다. 이번 장에서는 그러한 부분에 초점을 맞추어 사용자 입장에서 많이 고려하게 될 데이터모델이나 HQL과 같은 부분을 살펴보겠습니다.
데이터모델
하이브에서 데이터는 아래와 같은 주요 객체를 통해 구조화 됩니다: 데이터베이스, 테이블, 파티션, 버킷, 뷰 그리고 데이터타입들.
데이터베이스
(실제 데이터를 포함하지 않으나) 테이블의 그룹
테이블
관계형 데이터베이스의 테이블에 상응하는 객체입니다. 각 테이블은 해당되는 HDFS 디렉토리를 가집니다 (하지만 모든 데이터가 subpath에 존재하지 않을 수 있습니다). 그리고 테이블 안에 있는 데이터는 직렬화 되어 저장됩니다. 사용자는 테이블에 데이터의 직렬화 포맷을 설정해둘 수 있습니다. 하이브는 빌트인 직렬화 포맷을 제공하여 압축이나 lazy deserializtion 등에 사용할 수 있습니다. 또한, custom SerDe를 만들어 사용할 수도 있습니다. 직렬화 포맷 설정은 테이블 카탈로그(또는 파티션에)에 설정되어 하이브 쿼리 수행 시 데이터에 접근할 때 자동적으로 사용하게 됩니다. 하이브는 HDFS, NFS, 로컬 디렉토리 등의 저장소를 지원합니다.
파티션
각 테이블은 여러 개의 파티션을 가질 수 있습니다. 이러한 파티션은 테이블 하위의 데이터의 분배와 위치를 결정하게 됩니다(주로 테이블 디렉토리의 subpath에 위치시킵니다). 테이블 T의 데이터가 /wh/T 디렉토리에 있다고 가정하고, ds와 ctry라는 컬럼이 파티션으로 사용된다면 /wh/T/ds=20090101/ctry=US 와 같은 형태로 파티션이 위치하게 됩니다.
파티션은 Data Scan을 줄여서 쿼리를 최적화하는데 큰 역할을 합니다. 위에서 SELECT * FROM T WHERE ds = 20090101 AND ctry = 'US' 와 같은 형태의 쿼리를 실행 시에, 해당 path의 파일만을 scan하기에 빠르게 실행될 수 있고, 리소스 사용량도 줄일 수 있게 됩니다.
버킷(Bucket)
각 파티션에 존재하는 데이터는 한 컬럼에 들어있는 값의 해쉬를 통해 버킷으로 나뉘어 질 수 있습니다. 만약 위의 파티션에서 다른 컬럼을 파티션으로 지속적으로 추가하게 된다면 너무 많은 파티션 디렉토리가 생성되게 됩니다. 그렇기에 사용자는 HQL의 'CLUSTER BY' 구문을 사용해서 한 컬럼에서 같은 값을 가진 행들은 같은 버킷에 저장할 수 있습니다. 그리고 WHERE, JOIN 같은 구문에서 파티션의 최적화와 같이 해당 되는 파일만 읽어 Data Scan을 줄입니다.
뷰(View)
뷰는 논리적 데이터 구조로 쿼리의 복잡함을 줄여서 간단하게 만드는 기능을 합니다. '논리적'이라고 표현된 이유는 뷰는 HDFS(또는 저장소) 상에 어떠한 데이터를 추가하지 않고 오로지 metastore에만 정의되어 관리되기 때문입니다. 관계형 데이터베이스의 뷰와 달리, HQL의 뷰는 어떠한 데이터도 저장하지 않고 materialized되지 않습니다. 뷰가 생성되면, 스키마는 즉시 고정됩니다. 뷰가 기반하는 테이블의 변경은 뷰 스키마에 반영되지 않습니다. 그렇기에 의존하는 테이블이 삭제되거나 변경되고 뷰에 접근하면 뷰에 접근 시점에 실패가 발생하게 됩니다. 또한, 뷰는 Read-Only입니다.
위에서 대략적인 아파치 하이브의 개념을 이해하셨다면, 아래 글에서의 Hands-On을 통해 실제 어떻게 사용하는지 살펴보실 수 있겠습니다 :)
Reference
[1] Hive - A Warehousing Solution Over a Map-Reduce Framework
[3] Apache Hive Essentials
[5] Internal Hive
[6] Improving the performance of Hadoop Hive by sharing scan and computation tasks
[7] Hive Design
반응형'Data' 카테고리의 다른 글
Apache Spark RDDs(Resilient Distributed Datasets)의 이점과 특징 (feat. DSM) (0) 2021.06.03 Apache Spark란? (0) 2021.06.01 Apache Spark(PySpark) Matrix Factorization 최적화하기 (0) 2021.05.15 [Hands On] 아파치 에어플로우 도커환경에서 핸즈온 - #1 기초 (Apache Airflow) (4) 2021.03.01 "데이터 경제를 위한 비지니스 모델"을 읽고 (feat. 한국 데이터 기업) (0) 2021.02.02 주니어 데이터 엔지니어의 공부방법 (6) 2021.01.27 데이터 품질 (Data Quality) (0) 2021.01.27 [Hands On] 도커 기반 하둡 살펴보기 (HDFS, YARN, MapReduce, Hive) (0) 2021.01.27