HCatalog 동적 파티셔닝(Dynamic Partitioning)
HCatalog 동적 파티셔닝(Dynamic Partitioning)
HCatalog에 데이터를 쓸 때 모든 레코드를 단일 파티션으로 쓸 수도 있고, 데이터 안의 파티션 컬럼 값을 이용해 여러 파티션으로 나눠 쓸 수도 있어요. 후자를 동적 파티셔닝(dynamic partitioning)이라고 합니다.
출처: 문서
본문
개요(Overview)
HCatalog에 데이터를 쓸 때 모든 레코드를 단일 파티션으로 쓸 수 있어요. 이 경우 파티션 컬럼은 출력 데이터에 있을 필요가 없습니다.
다음 Pig 스크립트가 이를 보여줘요:
A = load 'raw' using HCatLoader();
...
split Z into for_us if region='us', for_eu if region='eu', for_asia if region='asia';
store for_us into 'processed' using HCatStorer("ds=20110110, region=us");
store for_eu into 'processed' using HCatStorer("ds=20110110, region=eu");
store for_asia into 'processed' using HCatStorer("ds=20110110, region=asia");
여러 파티션에 동시에 데이터를 쓰고 싶다면 데이터에 파티션 컬럼을 넣고, 저장 시 파티션 값을 지정하지 않으면 돼요.
A = load 'raw' using HCatLoader();
...
store Z into 'processed' using HCatStorer();
동적 파티셔닝이 동작하는 방식은 이래요. HCatalog가 전달받은 데이터에서 파티션 컬럼을 찾아내고, 이 컬럼들의 데이터를 이용해 행들을 여러 파티션으로 나눕니다. (HCatalog에 전달되는 데이터는 반드시 대상 테이블의 스키마와 일치해야 하므로 항상 파티션 컬럼을 포함해야 해요.) 파티션 컬럼에 null 값이 있으면 전체 과정이 실패하므로 주의해야 합니다.
또한 단일 실행 중 생성되는 모든 파티션은 하나의 트랜잭션에 속해요. 따라서 과정 중 어느 하나라도 실패하면 어떤 파티션도 테이블에 추가되지 않습니다.
외부 테이블(External Tables)
이 섹션은 HCatalog 0.5, 0.12, 0.13에서 외부 테이블의 동적 파티션에 발생한 변경 사항을 설명해요.
HCatalog 0.5부터 외부 테이블의 동적 파티셔닝이 깨져 있었어요(HCATALOG-500). 이 문제는 Hive 0.12.0에서 외부 테이블의 동적 파티션을 사용자 지정이 아닌 메타데이터 기반 위치에 생성하도록 해서 고쳐졌어요(HIVE-5011). Hive 0.13.0부터는 잡 구성 속성 hcat.dynamic.partitioning.custom.pattern에 경로 패턴을 지정해 위치를 커스터마이즈할 수 있어요(HIVE-6109). 외부 테이블의 정적 파티션은 모든 Hive 릴리스에서 사용자 지정 위치를 가질 수 있습니다.
예를 들어 Hive 0.12.0에서 user_logs라는 테이블이 (year, month, day, hour, minute, country)로 파티셔닝되고 외부 위치가 "hdfs://hcat/data/user_logs"라면, 동적 파티션의 위치는 키와 값을 모두 포함하는 표준 Hive 형식이 돼요:
Hive 0.13.0 이상에서는 hcat.dynamic.partitioning.custom.pattern을 커스텀 경로 패턴으로 설정할 수 있어요. 예를 들어 패턴 "${year}/${month}/${day}/${hour}/${minute}/${country}"는 경로에서 키를 생략합니다:
각 동적 파티션 컬럼은 ${column_name} 형식으로 커스텀 위치 경로에 반드시 존재해야 하고, 커스텀 위치 경로는 모든 동적 파티션 컬럼으로 구성돼야 해요. 다른 유효한 커스텀 경로 문자열로는 다음이 있습니다:
- data/${year}/${month}/${day}/${country}
- ${year}‐${month}‐${day}/country=${country}
- output/yr=${year}/mon=${month}/day=${day}/geo=${country}
다른 예시는 HCatalog Configuration Properties를 참고하세요. 구현에 대한 자세한 내용은 HIVE-6019의 PDF 첨부를 보세요.
Hive 동적 파티션
Hive 동적 파티션에 대한 정보는 여기서 볼 수 있어요:
- Design Document for Dynamic Partitions
- Original design doc
- HIVE-936
- Tutorial: Dynamic-Partition Insert
- Hive DML: Dynamic Partition Inserts
Pig와 함께 사용하기(Usage with Pig)
Pig에서 사용하는 건 아주 간단해요! 보통 store를 위해 모든 키를 지정하는 대신, 실제로 필요한 키만 지정하면 됩니다. HCatOutputFormat은 필요할 때(키 값이 지정되지 않았을 때) 동적 파티셔닝 사용을 자동으로 감지해 데이터를 검사해 적절히 기록합니다.
그래서 이 문장은…
store A into 'mytable' using HCatStorer("a=1, b=1");
…데이터가 a=1이고 b=1인 값만 가진다면 아래 문장들 중 어느 것과도 동등해요:
store A into 'mytable' using HCatStorer();
store A into 'mytable' using HCatStorer("a=1");
store A into 'mytable' using HCatStorer("b=1");
반대로 데이터가 여러 파티션에 걸쳐 있다면 HCatOutputFormat이 데이터를 자동으로 적절히 나눠(spray) 기록해요.
예를 들어 데이터셋 전체에서 a=1이고 b가 1과 2 값을 가진다고 해 볼게요. 그러면 다음 문장은…
store A into 'mytable' using HCatStorer();
…다음 문장들 중 어느 것과도 동등합니다:
store A into 'mytable' using HCatStorer("a=1");
split A into A1 if b='1', A2 if b='2';
store A1 into 'mytable' using HCatStorer("a=1, b=1");
store A2 into 'mytable' using HCatStorer("a=1, b=2");
MapReduce에서 사용하기(Usage from MapReduce)
Pig에서와 마찬가지로, MapReduce 프로그래머가 동적 파티셔닝에서 보는 유일한 변화는 모든 파티션 키/값 조합을 지정할 필요가 없다는 점이에요.
(a=1, b=1) 특정 파티션에 쓰는 현재 코드 예시는 다음과 같아요:
Map<String, String> partitionValues = new HashMap<String, String>();
partitionValues.put("a", "1");
partitionValues.put("b", "1");
HCatTableInfo info = HCatTableInfo.getOutputTableInfo(dbName, tblName, partitionValues);
HCatOutputFormat.setOutput(job, info);
여러 파티션에 쓰려면 위 코드를 각각 담은 별도 잡(job)을 실행해야 했어요.
동적 파티셔닝을 쓰면 아는 키만큼만, 또는 필요한 만큼만 지정하면 돼요. 나머지 키는 자동으로 파악해 필요한 파티션을 만들어내므로, 단일 잡으로 여러 파티션을 생성할 수 있습니다.
더 알아보기 (Learn more)
동적 파티셔닝은 파티션 키를 미리 몰라도 데이터에 있는 값으로 자동 분류해 주는 편리한 기능이에요. 단, 파티션 컬럼에 null이 있으면 실패하므로 입력 데이터 검증을 꼭 해주세요.