Data Engineering/HBase

Hive Table 파티션 생성하고 데이터 붓기

quantapia 2019. 9. 23. 19:27

Partition 이란?

여러분이 알고 있는 Partition이 맞습니다.

 

키를 기준으로 물리적으로 같이 저장시켜서 빨리 검색가능하게 만드는거죠.

 

Non-Partition Table

 

create table salesdata(

salesperson_id int,  

product_id int,

date_of_sale string)

 

Partition Table

 

create table salesdata_p(

salesperson_id int,  

product_id int)

Partitioned By

(date_of_sale string)

 

여기서 문제.

 

create table salesdata_p_backup as select * from salesdata_p

 

새로 생긴 salesdata_p_backup 테이블은 파티션이 생길까요 안생길까요?

 

정답

안생깁니다. 

 

그럼 non-partition 테이블에서 partition 테이블로 데이터를 부으려면 어떻게 해야할까요? 

 

SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
SET hive.exec.max.dynamic.partitions=1000;
SET hive.exec.max.dynamic.partition.pernode=1000;

insert into salesdata_p partition(date_of_sale)
select * from salesdata_p_backup

 

이러면 들어갑니다.

 

만약 SET hive.exec.dynamic.partition.mode=nonstrict; 만 있는 경우 아래와 같은 에러를 만납니다.

Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask 

 

그리고 권한 주의하세요.

 

만약 root로 테이블을 만들고 서비스 계정으로 데이터를 부으면 아래와 같은 에러를 만납니다.

Return code 1 : org.apache.hadoop.hive.ql.exec.MoveTask

 

권한이 없다는 건데 root 로 테이블 만들고 서비스 계정으로 데이터 부으면 Insert 가 안됩니다.

Hadoop에 저장된 paque 파일에 접근 권한이 없는거죠.

 

 

테이블 마이그레이션

위에서 생성한 non-partitioned 테이블인 salesdata_source 에서 partitioned 테이블인 salesdata 로 데이터를 삽입하기 위해서는 다음과 같이 두 가지 방식이 존재한다.

  1. Static partitioning (SP)
  2. Dynamic partitioning(DP)

 

정적 파티션(static partitioning)

  • 정적 파티션은 data 삽입을 위해서 partition의 값을 명시적으로 입력해야 한다.

    • 아래와 같이 salesdata_source 에서 '10-27-2017' , '10-28-2017' 두 값으로 가져온 데이터를 파티셔닝 된 salesdata 에 넣으면서 파티션 값을 설정할 수 있다.

       

       

      insert into table salesdata partition (date_of_sale=’10-27-2017’)

      select * from salesdata_source where date_of_sale=’10-27-2017’;insert into table salesdata partition (date_of_sale=’10-28-2017’)select * from salesdata_source where date_of_sale=’10-28-2017’;

    • 결과적으로 아래와 같이 두 개의 파티션이 생성됨을 확인할 수 있다.

       

       

      show partitions salesdata;

      O/p:date_of_sale=’10-27-2017’date_of_sale=’10-28-2017’

  • 전체 데이터를 조회하면 값이나 출력 결과가 달라진 것은 없다. 하지만 내부적으로 데이터 들은 생성된 두개의 파티션에 데이터가 별도로 저장되어 있고, 그곳으로 부터 데이터를 읽어온다. 이 것은 HDFS (or Object Storage) 에서 값을 확인할 수 있다.

     

     

    hadoop fs -ls /apps/hive/warehouse/db_name.db/salesdata/

    O/p:/apps/hive/warehouse/db_name.db/salesdata/date_of_sale=10-27-2017/apps/hive/warehouse/db_name.db/salesdata/date_of_sale=10-28-2017

 

동적 파티션(dynamic partitioning)

  • 다른 방식으로 파티션 칼럼의 값을 기반으로 hive engine 이 동적으로 파티션을 수행할 수 있도록 하는 방식이 있다. 이것을 사용하기 전에 동적 파티션을 위해 아래와 같이 parameter 설정이 필요하다. 이는 의도 치 않게 hive 에 의해서 많은 수의 partition 들이 생성되는 것을 막기 위한 설정 값 이다.

     

     

    set hive.exec.dynamic.partition.mode=nonstrict;

  • 아래와 같이 동일하게 dynamic partition 을 수행할 수 있다. 여기서 주의할 점은 반드시 파티션 칼럼은 마지막 순서에 와야 한다는 것이다.

     

     

    hive> insert into table salesdata partition (date_of_sale)

    select salesperson_id,product_id,date_of_sale from salesdata_source ;

 

  • 이와 같이 동적 파티션을 사용하는 경우 hive engine 이 파티션 칼럼이 가지고 있는 unique 값들을 확인해서 각각의 값으로 파티션을 생성한다. 파티션의 최대 개수는 기본적으로 200 으로 별도의 설정을 통해 해당 값을 조절할 수 있다.

     

     

    set hive.exec.max.dynamic.partitions=1000;

    set hive.exec.max.dynamic.partitions.pernode=1000;


파티션의 필요성

위에서 생성한 테이블에 다음과 같은 쿼리를 수행해보자

 

 

select * from salesdata_source where salesperson_id=12 and date_of_sale =’10-28-2017’

salesdata_source 는 파티션이 되어 있지 않기 때문에 2017년 10월 28일 데이터를 읽기 위해서 full-scan 작업을 거쳐야 한다. 그러나 동일한 쿼리를 파티션이 된 salesdata 에 수행하는 경우, 10-28-2017 의 값을 갖는 파티션만 탐색하면 됨으로 훨씬 작은 자원과 시간으로 쿼리를 수행할 수 있다. 이러한 특성은 테이블이 커질 수록 점점 더 큰 성능 향상을 나타낸다.

 

External partitioned tables

이미 HDFS 상에 존재하는 데이터를 가지고 파티션 테이블을 생성할 수도 있다.

  • 만약 '/user/hive/text1.dat' 안에는 다음과 같이 파일 내용이 있다고 해보자

     

     

    salesperson_id|product_id|date_of_sale

    12|101|10-27-201710|10010|10-27-2017111|2010|10-27-2017

  • 위의 파일을 이용해서 아래와 같이 파티션 테이블을 생성할 수 있다.

     

     

    create external table salesdata_ext

    (salesperson_id int,product_id int)partitioned by (date_of_sale string)location ‘/user/hive/salesdata_ext/’

    그리고 아래와 같이 수동으로 partition 경로를 생성 한 후 데이터 파일을 해당 경로에 넣어 주면 된다.

     

     

    hadoop fs -mkdir /user/hive/salesdata_ext/date_of_sale=10-27-2017

    hadoop fs -cp /user/hive/text1.dat /user/hive/salesdata_ext/date_of_sale=10-27-2017/

    하지만 이 경우 partition 정보가 나오지 않는 현상이 발생 할 수 있는데, 이 경우 repair 를 통해서 정보를 갱신해 줘야 한다.

     

     

    Show partitions salesdata_ext;

    --0msck repair table salesdata_ext;show partitions salesdata_ext;O/p:date_of_sale=10-27-2017<or>alter table salesdata_ext add partition (date_of_sale=’10-27-2017’);show partitions salesdata_ext;O/p:date_of_sale=10-27-2017

 

파티션 수정

  • Drop 파티션, rename 파티션을 위해서는 alter 명령어를 통해 수행할 수 있다.

     

     

    --파티션 이름 변경

    1. alter table salesdata partition (date_of_sale=10-27-2017) rename to partition (date_of_sale=10-27-2018);-- 파티션 삭제 (내부 테이블)2. alter table salesdata drop partition (date_of_sale=10-27-2017) ; (internal table)-- 파티션 삭제 (외부 테이블)3. alter table salesdata_ext drop partition (date_of_sale=10-27-2017) ; (external table)

    • 내부 테이블의 경우 파티션 삭제 시 warehouse 의 하위 경로의 데이터도 같이 삭제가 되지만, 외부 테이블의 경우 파티션 삭제 시 warehouse 의 하위 경로는 삭제되지 않는다.
    • 반대로 warehouse 의 하위 파일들을 삭제하고 파티션을 삭제하지 않는다면, hive 관리 테이블에서 drop partition 하지 않는 이상 해당 파티션의 정보가 보인다.

 

 

  •