[Hive] tblproperties( 'skip.header.line.count'='1') 사용 시 주의할 점

참고: hive version 2.3.7에서 발생한 문제에 대한 글입니다.

Hive 테이블 생성 시

CREATE TABLE table1 (
	...
)
tblproperties('skip.header.line.count'='1');

위처럼 tblproperties('skip.header.line.count'='1') 설정을 적용하면 저장된 파일에서 1번째 row에 해당하는 헤더를 무시하고 정보를 읽어들인다. 이는 pandas DataFrame 등으로 데이터 작업 후 df.to_csv 같은 메서드를 활용해 헤더와 함께 저장했을 때 유용하다.

하지만 테이블을 백업하는 과정에서 마주친 문제점이 있다.

그 과정은 다음과 같다.
1. real.tablereal.table_20220211 테이블로 백업 (이 때, tblproperties('skip.header.line.count'='1') 도 마찬가지로 적용)
2. real.table 테이블의 일부 컬럼을 수정한 schema로 test.table생성 (마찬가지로 tblproperties('skip.header.line.count'='1') 적용)
3. real.table_20220211 에서 데이터를 읽어 들여 컬럼에 약간의 변환을 가한 뒤 test.table 에 과거 파티션 데이터 일괄 입수

이 과정에서 발생한 문제는, SELECT COUNT(1) FROM real.table의 결과와 SELECT COUNT(1) FROM real.table_20220210 의 결과는 같으나, 마지막으로 생성된 SELECT COUNT(1) FROM test.table의 결과가 다르다는 것이다. 마지막에 생성된 테이블의 record 수만 나머지 두 테이블보다 더 적었다.

이는 특정 테이블을 백업하고 그 백업 테이블로부터 필요한 과거 파티션의 row들을 빠짐없이 가져와야 하는 상황에서 걸림돌이 되었다.

문제를 파악하기 위해 구글링한 결과 이 곳에서 tblproperties('skip.header.line.count'='1') 가 원인임을 알 수 있었다.

이를 검증하기 위해 hadoop fs -text /user/hive/warehouse/real.db/table/{파티션명}/{일부데이터} > check.txt 와 같이 일부 파일을 하둡에서 가져온 후 확인해보았다.

파일은 다음과 같은 식이었다.

real.table 테이블의 개별 파일 예시

age	sex	country ...
10	M	USA ...
15	F South Korea ...
25	M	France ...

real.table_20220210테이블의 개별 파일 예시

10	M	USA ...
15	F South Korea ...
25	M	France ...

test.table 테이블의 개별 파일 예시

15	F South Korea ...
25	M	France ...

위와 같이 테이블에서 tblproperties('skip.header.line.count'='1') 설정이 적용된 다른 테이블로 데이터를 읽어갈 때마다 각 개별 파일 내의 첫 번째 줄이 생략되어 전달되었다. 이는 개별 파일의 수가 많은 테이블일수록 잃어버리는 정보의 양이 많다는 것을 의미한다.

+참고로 각 테이블로 데이터를 옮길 때에는 다음과 같은 식으로 쿼리를 사용하였다.

-- 컨테이너 메모리 초과 방지
SET hive.tez.container.size=4096;
-- 동적 파티션 설정
SET hive.exec.dynamic.partition.mode=nonstrict;

INSERT OVERWRITE TABLE real.table_20220210 PARTITION(exec_dt)
SELECT * FROM real.table

+참고로 처음에 'hive 쿼리를 통해서' 백업테이블에 데이터를 덮어쓸 때에는 tblproperties('skip.header.line.count'='1') 설정 여부에 상관없이 헤더 정보가 사라진 개별 파일이 각 파티션에 저장된다.

위 경험으로부터 얻은 교훈은, hive 테이블의tblproperties('skip.header.line.count'='1') 설정은 데이터를 헤더가 붙은 상태로 입수하여 바로 사용할 때에 편리하지만, 다른 테이블에서 위 설정이 적용되어 있는 또 다른 테이블로 hive를 통해서 데이터를 옮길 때에는 예상치 못한 채 정보를 손실할 수 있다는 것이다. (되돌릴 수 없는 과거의 데이터일 경우, 데이터를 일부 잃었다는 사실을 나중에 깨닫는다면 아주 끔찍할 것이다.)

물론 대부분의 경우 위 설정을 데이터 입수의 첫 부분에 해당하는 테이블에 사용하고 그 뒤에 처리된 피쳐들을 저장하는 테이블에는 사용할 일이 적겠지만, 나와 같이 데이터를 백업하고 과거 파티션들로부터 모든 데이터를 읽어와야 하는 경우라면 주의하는 것이 좋겠다.

과거 데이터를 새로운 테이블에 부어줄 때에만 잠시 아래와 같이 해당 설정을 UNSET 해줬다가 데이터를 부은 후 다시 설정해주는 것도 방법이고,

ALTER TABLE test.table
UNSET `tblproperties('skip.header.line.count'='1')`;
ALTER TABLE test.table
SET `tblproperties('skip.header.line.count'='1')`;

아예 해당 설정을 하지 않고 사용하되, 데이터 입수 시df.to_csv('my/path/data.csv', header=False)와 같이 (pandas 예) 헤더 정보를 제외하고 저장하는 것도 방법으로 보인다. (데이터 입수 코드 및 테이블 생성 ddl.sql 파일 히스토리를 코드 저장소에서 확인할 수 있기 때문에 컬럼 순서를 알 수 있다)

좋은 웹페이지 즐겨찾기