들어가며
3장은 데이터 마트를 구축하는 파이프라인을 분산 처리의 관점으로 살펴봅니다. 크게 보면 1) 분산스토리지에 저장된 데이터를 구조화
, 2) 열 지향 스토리지 형식으로 저장
, 3) 완성한 구조화 데이터를 결합,집계하여 데이터 마트(비정규) 생성
, 4) 배치 혹은 애드 훅 등 상황에 맞는 쿼리엔진으로 질의
의 순서로 이루어집니다. 이 과정에 핵심이 될 만한 내용 3가지를 추려보면 다음과 같습니다.
- 비구조화 데이터를 가공하는 과정
- 상황에 맞는 쿼리엔진
- 데이터 마트를 구축하기까지
1. 비구조화 데이터를 가공해보자
책에서 나온 구조화 데이터
라는 용어는 보통 정형 데이터
로, 비구조화 데이터
는 비정형 데이터
로 자주 표현합니다. 영어로도 structured
, unstructed
로 표현하기 때문에 책에 나온 표현 그대로를 사용하도록 하겠습니다.
먼저 구조화 데이터와 비구조화 데이터는 다음과 같이 정의됩니다.
- 구조화데이터(‘structured data’) : 스키마가 명확하게 정의된 데이터
- 비구조화데이터(‘unstructed data’) : 스키마가 없는 데이터. 텍스트, 미디어 데이터
- 반구조화데이터(‘Semi-structed data’) : 데이터의 서식은 정해져있으나 칼럼수,데이터형등 이 고정되지 않은 채 저장되는 데이터. Json, Xml 등
스키마리스 데이터
미리 정의된 스키마(데이터베이스에서 데이터의 구조, 타입, 관계 등을 명시하는 것) 없이도 저장할 수 있는 데이터를 의미합니다.
현실세계의 대부분의 데이터는 처음에 이 비구조화 데이터(비정형 데이터) 모양으로 존재하는데, 이 상태 그대로는 집계
처리가 불가능합니다. 따라서 앞으로 소개될 여러 소프트웨어들은 이 비구조화 데이터를 분산스토리지 등에 저장하여 분산시스템에서 처리, 가공
하는 과정이 필수적으로 선행되어야 하며, 이때 스키마를 정의하고 구조화된 데이터로 변환해줍니다. 특히 SQL 집계를 위해 구조화 데이터로 변환하는 과정에서는 데이터의 압축률을 높이기 휘해 열 지향 스토리지
로 저장합니다.
이 열 지향 스토리지
로 저장하는 방법은 두가지가 있는데요, 하나는 제품마다 미리 스토리지 형식이 고정되어 있는 MPP 데이터베이스
를 사용하는 것이고, 다른 하나는 Hadoop을 사용에 사용자가 직접 열 지향 스토리지의 형식을 선택하고 쿼리엔진으로 집계하는 방식입니다.
Hadoop은 분산 파일 시스템인 HDFS(Hadoop distributed file system), 리소스 관리자인 YARN(Yet Another Resource Negotiator), 분산 데이터 처리를 위한 MapReduce 로 구성되어 있고, 이외 다양한 소프트웨어로 대체 혹은 조합하여 시스템을 구합니다. YARN은 가용 가능한 자원인 CPU와 메모리를 묶어 컨테이너(container) 라는 단위로 관리하며 MapReduce 역시 컨테이너 상에서 동작합니다. 이 MapReduce는 비구조화 데이터를 가공하는 데 적합합니다.
컬럼 기반(columnar) 스토리지 포맷
- Apache Parquet
- Apache Parquet은 Hadoop 생태계에서 널리 사용되는 오픈 소스 컬럼 기반 스토리지 포맷입니다. Parquet은 복잡한 중첩 데이터 구조를 효율적으로 저장하고, 데이터 압축 및 인코딩 기능을 제공하여 스토리지 비용을 절감하고 쿼리 성능을 개선합니다. Hadoop과 더불어 Apache Spark, Apache Impala, Apache Drill 등 다양한 데이터 처리 프레임워크와 호환됩니다.
- Apache ORC (Optimized Row Columnar)
- ORC는 Apache Hive 프로젝트에 의해 개발된 컬럼 기반의 데이터 스토리지 포맷입니다. ORC는 높은 압축 비율과 효율적인 읽기 성능을 제공하며, 특히 Hive에서의 대규모 데이터 웨어하우스 작업에 최적화되어 있습니다. ORC는 데이터의 스트라이프 구조를 사용하여 대용량 데이터 처리를 빠르고 효율적으로 할 수 있도록 설계되었습니다.
- Avro
- Avro는 행 기반(row-oriented)과 컬럼 기반 스토리지 모두를 지원하는 데이터 직렬화 시스템입니다. Avro는 스키마가 데이터와 함께 저장되어, 데이터가 어떻게 해석되어야 하는지 명확하게 합니다. 이는 데이터 스키마가 시간에 따라 변할 수 있는 대규모 데이터 처리에 유용합니다. Avro 파일은 Hadoop에서 효율적인 데이터 스토리지 및 빠른 데이터 직렬화/역직렬화를 위해 사용됩니다.
- Apache CarbonData
- Apache CarbonData는 Hadoop 생태계를 위한 새로운 컬럼 기반 스토리지 포맷입니다. CarbonData는 뛰어난 압축 기능과 인덱싱 메커니즘을 제공하여, 고성능의 인터랙티브 쿼리와 빠른 데이터 처리를 지원합니다. 또한, 다양한 데이터 소스와의 통합과 복잡한 데이터 유형의 처리를 지원하여, 실시간 분석과 데이터 레이크에 이상적입니다.
2. 쿼리 엔진도 상황에 맞게 써야 한다.
반면 가공이 아닌 집계
가 목적이라면, ‘집계’를 위해 설계된 쿼리 엔진
을 사용할 수 있습니다.
- Apache Hive (여기서는 Hive on MR)
- 쿼리를 자동으로 MapReduce 프로그램으로 변환합니다. 대량의 데이터를 배치처리하기 위한 시스템으로, 한번 실행하면 대량의 데이터를 읽지만 작은 프로그램을 실행하기에는 오버헤드가 너무 크기 때문에 시간이 걸리는 배치처리는 적합하나 애드 훅 쿼리를 여러번 실행하는 데는 부적합합니다.
- Hive On Tez : MR처럼 1회의 MapReduce 스테이지의 종료를 기다리지 않고, 처리가 끝난 데이터를 차례로 후속 처리에 전달함으로써 쿼리 전체의 실행 시간을 단축시킵니다.
- Apache Impala, Presto
- Hive를 고속화하는 방안이 아니라, 처음부터 대화형 쿼리 실행을 전문으로 하는 쿼리 엔진입니다. Hive on MR, Tez 는 장시간의 배치를 가정해 한정된 리소스를 유효하게 활용하도록 했지만, impala & presto는
순간 최대속도를 내기 위해 모든 오버헤드가 제거
되어 사용 가능한 리소스를 최대한 활용하는 식입니다. MPP 데이터베이스처럼 가능한 많은 데이터를 병렬처리함으로써 고속화를 구현합니다.
- Hive를 고속화하는 방안이 아니라, 처음부터 대화형 쿼리 실행을 전문으로 하는 쿼리 엔진입니다. Hive on MR, Tez 는 장시간의 배치를 가정해 한정된 리소스를 유효하게 활용하도록 했지만, impala & presto는
- Apache Spark
- Spark는 인메모리 형태의 고속 데이터 처리 프로젝트 입니다. 컴퓨터에서 취급가능한 메모리의 양이 증가함에 따라
가능한 많은 데이터를 메모리상에 올려두고 사용
하며, 중간에 비정상 종료 되어 날아가더라도 다시 처리하면 된다는 개념을 가지고 있습니다. MapReduce를 대체하는 존재이며, SQL 실행을 위한 SparkSQL과 스트림처리를 위한 Spark Streaming 기능이 처음부터 내포되어 있습니다.
- Spark는 인메모리 형태의 고속 데이터 처리 프로젝트 입니다. 컴퓨터에서 취급가능한 메모리의 양이 증가함에 따라
책에서는 간단한 예제를 통해, Hive에 의한 구조화 데이터 작성
부터 살펴봅니다. 책에서의 예시를 통해 presto 등 사용하려는 쿼리엔진에 최적화된 형식으로 스토리지 포맷을 선택하며, 서브쿼리를 동해 팩트 테이블의 양을 줄이거나 데이터 편향을 고려한 쿼리의 예시를 보여줍니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
hive>
## 예시1) ORC 형식으로 테이블 생성
CREATE TABLE access_log_orc STORED AS ORC AS
SELECT cast(time AS timestamp) time,
request,
status,
cast(bytes AS bigint) bytes
FROM access_log_csv
;
## 예시2) 보다 효율적인 쿼리
SELECT data, count(*) users
FROM(
# 최초에 중복을 없앤다.
SELECT DISTINCT data, user_id FROM access_log
) t
GROUP BY date
;
책에서 소개된 내용을 토대로, 배치 목적의 Hive보다 대화형 쿼리 엔진인 Presto가 가진 장점은 다음과 같습니다.
- 쿼리 실행의 지연을 감소시키는 것을 목적으로 개발된 것이
대화형 쿼리엔진
입니다. - Presto는 플러그인 가능한 스토리지 설계로, 전용 스토리지 없이도 다양한 데이터소스에서 데이터를 읽어들입니다.
- Hive에서 만든 구조화데이터를 다시 재집계하는 목적에 적합합니다.
- 특히 ORC 형식의 로드에 최적화되어 있으며, 스토리지가 열 지향 데이터 구조로 되어 있는 경우에 성능을 최대한으로 발휘할 수 있습니다.
- Presto는 SQL 실행에 특화되어 있고, 쿼리를 분석하여 나온 최적의 실행 계획을 생성하여 자바 바이트 코드로 변환합니다. 변환된 바이트 코드는 Presto의 워커노드에 배포되고, 런타임 시스템에 의해 기계코드로 컴파일됩니다. 코드는 멀티스레드화되어 단일머신에서 수백 task씩 병렬수행이 가능합니다.
- Presto는 Hive 와 달리 쿼리의 실행과정에서 디스크에 쓰기를 하지 않습니다.
Presto
는 점점 그 목적에 부합하는 형태로 진화해 왔고, 현재는 기존의 것을 리브랜딩한 Trino
라는 솔루션이 많이 사용되고 있습니다. 사실 저도 얼마전 선릉에서 진행된 한국 Trino 3차 밋업에 잠시 참여하여 강연을 들었는데 유익하고 좋은 내용들이 많았습니다. 관심있으신 분들은 찾아보시면 좋을 것 같습니다.
3. 데이터 마트를 구축해보자.
결국 이 모든것은 데이터 마트를 구축하여 쓰기 위함입니다. 데이터 마트를 구축하기 위한 구성요소를 요약하여 표현하면 다음과 같습니다.
팩트 테이블
만들기- 추가 : 새로운 데이터를 증분으로 추가하는 방법입니다.
- 치환 : 과거의 데이터를 포함하여 테이블 전체를 다시 만드는 방법입니다.
- 효율을 보면 추가가 압도적으로 유리하지만, 관리상의 이유로 테이블에 결손, 중복등이 발생할 소지가 있습니다. 이를 위해 테이블 파티셔닝을 사용하며, 1일 1회 혹은 1시간 1회로 새 파티션 을 만들고, 이를 팩트 테이블에 붙여놓는 방식을 사용합니다. 각 파티션은 매번 교체되며, 만약 이미 존재한다면 덮어씁니다.
집계 테이블
만들기- 팩트 테이블을 요약한 테이블이며, 꼭 필요한 칼럼을 정하여 각 칼럼이 취하는 값의 범위인 카디널리티(cardinality)를 조정합니다. 너무 많이 줄이면 정보 손실이 있을 수 있습니다.
마스터 테이블
을 관리하는 방법- 스냅샷 테이블(snapshot table) : 정기적으로 마스터 테이블 전체를 통으로 저장합니다.
- 이력 테이블(history table) : 변경 내용만을 저장합니다.
- 비정규화 테이블 만들기
- 팩트 테이블과 디멘전 테이블을 결합하여 비정규화 테이블을 만든다.
정리하며
이번 장의 내용은 정리하면 다음과 같습니다.
- 비구조화 상태의 데이터를 구조화 상태로 변환하여 집계합니다. 이를 위해 많이 익숙한 Hadoop, Spark등을 널리 이용합니다.
- Hive는 디스크상에서 대량의 데이터를 처리하는데 적합하며, Presto(Trino), Impala등의 엔진은 메모리상에서 고속(대화형)으로 집계하는데 적합합니다.
- 데이터 마트는 팩트 테이블과 디멘전 테이블을 효율적으로 결합&집계하여 비정규화 테이블 형태로 만듭니다.
참고문헌
- [출처] 니시다 케이스케(Keisuke Nishida), ⌜빅데이터를 지탱하는 기술(BIG DATA WO SASAERU GIJUTSU)⌟, 장성두 옮김, 주식회사 제이펍
- https://pandio.com/difference-between-trino-and-prestodb/
- https://medium.com/@CodeDemon/columnar-file-format-for-big-data-analytics-25dd3ba01b63
- https://www.upsolver.com/blog/the-file-format-fundamentals-of-big-data
- https://jsonobject.tistory.com/564