티스토리 뷰

반응형

개요

hive 는 쿼리기반으로 데이터를 분석하기 위한 도구이다. 스키마는 메타스토어의 DBMS에 저장되지만 실제 데이터는 기본적으로는 HDFS 에 저장되어 있다. 그래서 hive 에서 논리적으로 테이블, 파티션, 버킷이라고 부르지만, 물리적으로 데이터가 어떻게 저장되어있냐? 하는 관점에서 생각하면 HDFS 의 폴더와 파일로 생각할 수 있다. 하둡 패키지에 따라 root 폴더는 다르겠지만 아래와 같은 폴더 구조로 저장된다는말이다.

/apps/hive/warehouse/<디비명>.db/<테이블명>/<파티션필드>=<파티션값>/

예를 들면, 이런 폴더 구조를 생각하면 쉽다

  • (db폴더) /apps/hive/warehouse/temp.db
    • (table 폴더) /apps/hive/warehouse/temp.db/t_foo (파티션 없는 temp.t_foo 테이블)
      • (기냥 파일) /apps/hive/warehouse/temp.db/t_foo/output.txt
    • (table 폴더)/apps/hive/warehouse/temp.db/t_sample (파티션 ymd 필드인 temp.t_sample 테이블)
      • (partition 폴더) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01
        • (bucket 파일) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01/000001_0
        • (bucket 파일) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01/000002_0
        • (bucket 파일) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01/000003_0
        • (bucket 파일) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01/000004_0
        • (bucket 파일) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01/000005_0
        • (bucket 파일) /apps/hive/warehouse/temp.db/t_sample/ymd=2021-01-01/000006_0

테이블과 HDFS 폴더

hive 에서 다음과 같이 temp.t_sample 이라는 테이블의 데이터는 어디에 존재할까?

hive> select * from temp.t_sample;

하둡패키지나 세팅에 따라 다르겠지만 내가 사용중인 HDP 패키지에서는 다음과 같은 hdfs 경로에 존재한다.

스키마 정보는 hive 의 메타스토어에 저장되지만, 실제 데이터는 다음과 같이 hdfs 에 저장되는게 일반적이라는 말이다.

% hadoop fs -ls /apps/hive/warehouse/temp.db
drwxrwxrwx   - hive hadoop          0 2021-11-10 18:28 /apps/hive/warehouse/temp.db/t_sample
drwxrwxrwx   - hive hadoop          0 2021-11-19 18:10 /apps/hive/warehouse/temp.db/user

파티션과 HDFS 폴더

그럼 hive 에서 파티션은 뭘까? hive 에서는 파티션을 지정할 수 있고 where 조건에 파티션필드를 사용하면 성능에도 유리하다.

예를 들어서 ymd 라는 파티션필드를 만들었고 다음과 같이 되어있다면 어떻게 구성될까? 

파티션 필드는 데이터에 존재하는게 아니라 사실 sub directory 구조로 되어있다.

hive> select * from temp.t_sample where ymd = '2021-10-10';

예를 들면 다음과 같다. 테이블에 맵핑된 hdfs 경로를 확인해보면, 다음과 같이 "필드명=값" 형태의 하위 폴더가 존재한다.

이게 hive 에서의 파티션 실체다. 이렇게 폴더구조로 하면 불필요한 파티션(=폴더)를 읽을 필요가 없기 때문에 성능에 유리하다.

% hadoop fs -ls /apps/hive/warehouse/temp.db/t_sample
drwxrwxrwx   - hive hadoop          0 2021-10-09 01:01 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-10-08
drwxrwxrwx   - hive hadoop          0 2021-10-10 01:22 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-10-09
drwxrwxrwx   - hive hadoop          0 2021-10-11 01:28 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-10-10
drwxrwxrwx   - hive hadoop          0 2021-10-12 01:12 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-10-11

단, 파티션이 너무 잘게 쪼개지면 파티션 정보를 저장한 메타스토어에서 파티션 정보를 가져와서 체크하는것도 오래걸리기 때문에, 일반적으로는 hive의 파티션은 날짜나 시간 파티션을 많이 쓰게된다. 

버킷과 HDFS 파일

버킷은 쉽게생각하면 저장된 파일을 생각하면 된다. 파티션 폴더안에 보면 여러개의 파일로 조각나서 저장되어있고 하나의 파일 덩어리를 버킷이라고 부른다.  쉽게 생각해서 아래 파티션의 경우 6개의 버킷으로 구성되어있다고 생각하면 된다.

파일갯수 = 버킷갯수
% hadoop fs -ls /apps/hive/warehouse/temp.db/t_sample/ymd=2021-10-11
Found 6 items
-rwxrwxrwx   3 hive hadoop      44182 2021-10-12 02:41 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-11-18/000001_0
-rwxrwxrwx   3 hive hadoop      13696 2021-10-12 02:41 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-11-18/000002_0
-rwxrwxrwx   3 hive hadoop      54296 2021-10-12 02:41 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-11-18/000003_0
-rwxrwxrwx   3 hive hadoop      93838 2021-10-12 02:41 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-11-18/000004_0
-rwxrwxrwx   3 hive hadoop      54711 2021-10-12 02:41 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-11-18/000005_0
-rwxrwxrwx   3 hive hadoop      24015 2021-10-12 02:41 /apps/hive/warehouse/temp.db/t_sample/ymd=2021-11-18/000006_0

버킷의 갯수 의미는 map/reduce 엔진에서 병렬처리할 때 태스크의 갯수와 의미가 있다. 파일이 6개면 처리하는 태스크가 6개였다는 결론이 된다. 그리고 파일저장할때 같은 필드값을 동일한 파일에 정렬후 저장하게 구성할 수 있다. 

버킷을 할 때의 장점과 예시

이렇게 되면 장점이 생기는데, 예를 들어 이름 필드를 기준으로 6개의 버킷으로 구성한다고 가정하면 아래와 같이 파일을 쪼개서 저장할 수 있다. 파일별로 필드의 min, max 값을 알고 있다면 full scan 할 필요 없이, 어떤 파일만 보면 되는지 찾을 수 있어서 성능에 유리하게 된다. (만약 통계값이 없더라도 정렬해서 저장되어있다면 해당 필드 한정으로 바이너리 서치 형태로 찾을수 있으니 역시 빨리 찾을 수 있다)

 

예를 들어, 아래 그림과 같이 "이름" 필드로 버킷팅을 했다면 min, max값만 체크후 0000003_0 파일만 스캔하면 된다는걸 알 수 있다. 

버킷팅 형태로 파일을 저장했다면? (6개로 버킷팅 했다고 가정)

즉 정리하면, 특정필드의 값이 같은 파일에 저장되도록 버킷팅을 할 때의 장점은 크게 2가지가 있다.

- 첫째, 동일한 값이 같은파일에 있어서 압축효율이 높아진다.
- 둘째, 2개의 테이블이 같은 필드로 버킷팅 하면 SMB Join 을 쓸 수 있어서 join 성능이 좋아진다.

물론, SMB(Sort-Merge_Bucket Join) 의 경우 버킷갯수가 배수로 떨어져야 하고, 기준필드를 같은걸로 구성해서 insert 시점부터 고려해야 한다는 제약이 있다. (쉽게 생각해서 저장하는 시점부터 고려해야 한다는 말)

그래도 사실상 hive에서 큰테이블 x 큰테이블의 JOIN 성능을 개선할 수 있는 사실상 유일한 튜닝방법이라 원리를 알아두면 나쁠것 없다. 실제로 map join 으로 유도가 안되는 케이스를 SMB 로 유도하게 재설계 해서 성능을 개선한 케이스가 있긴하다. (물론 단점도 있는데 이건 딴 글에서 다루도록 하겠다)

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함