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 로 데이터를 삽입하기 위해서는 다음과 같이 두 가지 방식이 존재한다.
- Static partitioning (SP)
- 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 하지 않는 이상 해당 파티션의 정보가 보인다.