본문 바로가기

Hadoop/Hudi

[Apache Hudi] 3-2. Components - Table Type & Query Type

hudi의 table과 Table 타입, 그리고 쿼리 타입에 대해 정리해보고자 한다.

Table Type

hudi는 두가지 테이블타입을 지원한다.

  • Copy On Write: Columnar File Format(parquet)으로 데이터를 저장한다. 데이터를 쓸때 이전의 base file과 새로들어온 데이터를 병합하여 새로운 버전의 base file을 생성한다.
  • Merge On Read: Columnar File Format(parquet) + Row Based File Format(avro)파일로 결합하여 저장된다. 업데이트 되는 신규 파일은 먼저 Avro포멧으로 생성된 Delta File에 먼저 쓰여지며, 이후 Compaction 작업을 통해 기존의 base file + Delta File을 병합하여 새로운 버전의 base file을 생성하게 된다.

1) Copy On Write

위에 간단히 설명한것처럼 새로운 데이터가 들어오면 기존에 저장된  Base File(parquet)에 새로운 데이터를 병합하여 새로운 버전의 Base File을 만든다.
데이터의 병합은 매 커밋이 발생할 때마다 수행될때마다 수행된다. 

  • 장점: 모든 데이터가 적은 수의 base file에 저장됨으로 읽기 성능이 빠르다.
  • 단점: 단 한건만 저장이 되더라도, 기존의 base  file의 데이터와 병합을 진행함으로 쓰기작업이 비효율 적이다. 또한 매 커밋마다 파일 병합작업을 진행함으로 write가 빈번하게 발생하는 workload에는 맞지 않는다.

<Copy On Write 타입의 작동 순서>

출처: https://hudi.apache.org/docs/table_types

  1. Insert / Upsert 오퍼레이션이 10시 10분에 커밋이 이루어진다.
  2. Copy On Write는 Columnar File Format인 parquet으로 저장됨으로, 필드에 따라 여러 파일로 쪼개저 저장되어있다.
    1. 10시 10분에 새로운 커밋이 발생하여, 필드에 따라 1,2,4번 파일에 써졌다.
    2. 이때 1,2번 필드는 기존에 10시 05분에 써진 base file이 존재하기 때문에 새로 커밋된 Insert/Update 오퍼레이션 데이터와 머지되어 새로운 버전의 10시 10분 base file이 생성되었다.
    3. 10시 10분 커밋은 3번 필드의 데이터는 저장하지 않음으로, 10시 05분 데이터로 남겨져 있게된다.
    4. 4번 필드 파일은 기존에 base file이 존재하지 않았기 때문에 바로 10시 10분 데이터가 쓰여지게 된다.
  3. "BEFORE COMMIT 10:10" 쿼리가 수행되면 Timeline에서 10시10분 이전의 커밋을 찾고, 이를통해 10시 05분이 10시10분 이전의 커밋이라는 것을 찾아내고, 10시 05분 데이터가 저장된 필드1, 필드2, 필드 3 파일을 읽어 데이터를 추출한다.
  4. "AFTER COMMIT 10:10" 쿼리 수행되면 timeline에서 10시 10분에 커밋된 내용을 찾아내고, 이를 통해 가장 최근에 생성된 베이스파일을 찾아내 쿼리 한다.

2) Merge On Read

기본 데이터는 parquet 포멧의 base file에 저장되고, 업데이트가 발생할때마다 Delta File이라고 하는 avro 파일에 기록한다. 이후 sync 또는 async방식으로 컴팩션을 수행하여 base file + delta file을 새로운 버전의 base file로 생성한다.

  • 장점: Update가 빈번하게 발생하는 workload에서의 성능이 보장된다.
  • 단점: 쿼리에 따라 base file + delta file을 모두 읽어야 하기 때문에 읽기 성능이 Copy On Write보다 떨어진다.

<Merge On Read 타입의 작동 순서>

출처:https://hudi.apache.org/docs/table_types

  1. timeline을 보면 1분에 한번씩 커밋이 발생하는것을 알수 있다.
  2. timeline의 데이터를 보면 10시 05분 컴팩션이 발생했음으로 base file에는(그린 색)에는 과거 base file와 delta file이 병합된 데이터(10시 05분 데이터)가 저장된다.
  3. 10시 10분에 Insert/Update 작업이 커밋되면 2번, 4번 필드의 Delta File(이미지의 Row based, Append Log)에 추가 된다.
  4. 다음 컴팩션이 발생할때까지 계속 Delta File에 쌓이게 된다.
  5. Query Optimized 쿼리는 Delta File을 제외한 base file에서만 결과를 읽어온다.
    Snapshot Query(Realtime Query)는 base file + delta file을 모두 읽어 쿼리 결과를 반환한다.

 

Query Type

테이블 타입에 따라 수행 가능한 쿼리 타입이 나뉘게 된다.

Table Type 지원되는 Query Type
Copy On Write Snapshot(스냅샷), Incremental(증분)
Merge On Read Snapshot(스냅샷), Incremental(증분), Read Optimized(읽기 최적화)
  • Snapshot Queries: 마지막 커밋이나, 마지막 컴팩션을 통해 생성된 맨 마지막의 스냅샷 파일(base file)을 읽어 쿼리를 수행한다.
    • Merge On Read 타입일 경우: 최신의 파일 슬라이스(base file + delta log file)을 모두 읽어 병합한후 결과를 조회한다. near real time 데이터를 제공할 수 있다.
    • Copy On Write 타입일 경우: 가장 최근의 파일슬라이스(parquet base file)만을 읽어 결과를 조회한다.
  • Incremental Queries: 증분 쿼리는 커밋/컴팩션 작업 이후 생성된 데이터만을 조회한다.
  • Read Optimized Queries: Merge On Read는 parquet으로 된 base 파일과, avro포멧인 delta 파일로 구성이 되는데, 이 쿼리는 parquet파일인 base file만 읽어 결과를 조회한다. 이는 컴팩션이 완료된 베이스파일만 읽음으로 쿼리 속도는 빠르지만, 아직 컴팩션이 되지 않은 delta파일은 읽지 않아 최신 데이터는 읽을 수 없다.

 

Query Type에 따른 수행 결과

1) Copy On Write 타입 테이블에서의 쿼리 수행

(캡쳐 화면에서 Read Optimized로 되어있지만 Snapshot 으로 보면 된다)

  1. time=0에 A,B,C,D,E 데이터가 커밋이 된다면 file 0, 1, 2에 적절히 분산되어 저장된다.
    1. Snapshot쿼리: base file을 읽어 처리하면으로 A, B, C, D, E를 모두 일는다.
    2. Incremental쿼리: 아무것도 없는 상황에서 A, B, C, D, E가 들어왔기 때문에 A, B, C, D, E 모두를 읽을 수 있다.

  1. D=>D', A=>A'로 업데이트 되는 데이터가 들어오면서 time=1 커밋이 발생한다.
  2. Copy On Write는 커밋 발생시마다 이전버전의 base file과 새로 들어온 데이터를 읽어 병합후 새로운 base file을 생성한다. 
    1. Snapshot 쿼리: 모든 베이스 파일에서 데이터를 읽기 때문에 File 0', File 1', File 2 를 읽어 A', B, C, D', E 를 읽는다.
    2. Incremental 쿼리:  기존 base파일에서 새로운 데이터만 읽기 때문에 A', D'만 읽는다.

  1. E=>E', A'=>A''로 업데이트, F Insert가 수행되어 time=2 commit이 발생한다.
  2. File 0' 의 A'와 A''를 병합하여 새로운 File 0''이 생성된다. 또한 E'를 업데이트, F를 인서트 하기 위해 File 2 데이터를 병합하여 새로운 File 2'를 읽는다.
    1. Snapshot 쿼리: 가장 최근의 base file을 읽어 처리함으로 File 0'', File 1', File 2'를 읽어 A'', B, C, D', E', F를 리턴한다.
    2. Incremental 쿼리: 변경 데이터인 A'', E', F를 리턴한다.

1) Merge On Read 타입 테이블에서의 쿼리 수행

  1. time=0에 A, B, C, D, E 데이터가 들어와 커밋된다.
    1. Snapshot 쿼리 : base file+ delta file을 읽는다. 아직 delta file이 없음으로 A, B, C, D, E를 그대로 읽는다.
    2. Incremental 쿼리: 아무것도 없는 상황에서 A, B, C, D, E가 들어왔기 때문에 A, B, C, D, E 모두를 읽을 수 있다.
    3. Read-Optimized: delta file을 제외한 base file에서만 읽기 때문에 A, B, C, D, E를 그대로 읽는다.

 

  1. D=>D', A=>A'로 업데이트 되는 데이터가 들어오면서 time=1 커밋이 발생한다.
  2. 이때 파란색 base file에 그대로 병합되는것이 아니라 노란색으로 표현된 Delta file에 데이터가 쓰여진다.
    1. Snapshot 쿼리 : base file+ delta file을 읽는다.  그러므로 A', B, C, D', E를 리턴한다.
    2. Incremental 쿼리: delta 파일에서만 데이터를 읽는다, A', D'를 리턴한다.
    3. Read-Optimized: delta file을 제외한 base file에서만 읽기 때문에 A, B, C, D, E를 그대로 읽는다.

 

  1. E=>E', A'=>A''로 업데이트, F Insert가 수행되어 time=2 commit이 발생한다.
  2. Log 0 파일에 A''를 추가하고, 새로 Log 2 파일을 생성한후 E', F를 append 한다.
    1. Snapshot 쿼리 : base file+ delta file을 읽는다.  그러므로 A'', B, C, D', E', F를 리턴한다.
    2. Incremental 쿼리: delta 파일에서만 데이터를 읽는다, A'', E', F 를 리턴한다.
    3. Read-Optimized: delta file을 제외한 base file에서만 읽기 때문에 A, B, C, D, E를 그대로 읽는다.

 

  1. 컴팩션이 수행되어 새로운 버전의 base file(하늘색)이 생성된다.
    1. Snapshot 쿼리 : base file+ delta file을 읽지만, Delta파일이 존재하지 않음으로 최신버전의 base file에서만 읽어온다.  그러므로 이전 단계와 동일한 A'', B, C, D', E', F를 리턴한다.
    2. Incremental 쿼리: 컴팩션이 수행되며 delta file이 없어졌음으로 아무것도 리턴하지 않는다.
    3. Read-Optimized: delta file을 제외한 base file에서만 읽기 때문에 Snapshot 쿼리와 동일한 A'', B, C, D', E', F 를 리턴한다.

출처:

 

 

'Hadoop > Hudi' 카테고리의 다른 글

[Apache Hudi] 3-1. Components - Timeline  (0) 2022.01.20
[Apache Hudi] 2. 파일 구조  (0) 2022.01.20
[Apache hudi] 1. hudi란 무엇일까?  (0) 2022.01.19