HDFS 에서 파티션 디렉터리를 직접 지웠는데 SHOW PARTITIONS 에는 그대로 남아 있다. 디렉터리 이름을 보면 dt=2022-11-11 15%3A11 처럼 %3A 가 섞여 있고, 그 이름을 그대로 넣어 ALTER TABLE ... DROP PARTITION 을 해도 지워지지 않는다.
디렉터리를 지우는 것과 메타스토어에서 파티션을 지우는 것은 별개다. 외부에서 디렉터리만 지우면 메타스토어에는 항목이 남는다. 여기까지는 일반적인 이야기이고, 이 사례의 진짜 함정은 이름의 이스케이프다.
Hive 는 파티션 값을 디렉터리 경로로 만들 때 경로에 쓸 수 없거나 모호한 문자를 퍼센트 인코딩한다. : 는 %3A 로, = 는 %3D 로, / 는 %2F 로 바뀐다. 공백은 이 대상에 들어 있지 않아 그대로 남는다. 그래서 값이 2022-11-11 15:11 인 파티션의 디렉터리 이름은 dt=2022-11-11 15%3A11 이 된다.
메타스토어에 저장된 값은 인코딩 전 원본이다. 따라서 DDL 에서는 디코드된 값을 써야 한다.
ALTER TABLE db.tbl DROP IF EXISTS PARTITION (dt='2022-11-11 15:11');
디렉터리에서 본 %3A 를 그대로 넣으면 % · 3 · A 세 글자를 값으로 가진 다른 파티션을 찾게 되어 아무것도 지워지지 않는다. IF EXISTS 때문에 오류도 나지 않아 성공한 것처럼 보이는 것이 더 나쁘다.
기준은 언제나 SHOW PARTITIONS 의 출력이다. 이 출력은 디코드된 값을 보여주므로, 거기 보이는 문자열을 그대로 따옴표 안에 넣으면 된다.
SHOW PARTITIONS db.tbl;
dt=2022-11-11 15:11
공백은 별도 처리가 필요 없다. 값 전체를 작은따옴표로 감싸면 그만이다.
여러 개를 한 번에 정리할 때는 쉼표로 나열한다.
ALTER TABLE db.tbl DROP IF EXISTS
PARTITION (dt='2022-11-11 15:11'),
PARTITION (dt='2022-11-11 16:11');
디렉터리가 사라진 파티션이 많으면 하나씩 지우는 대신 일괄 정리를 쓴다.
MSCK REPAIR TABLE db.tbl DROP PARTITIONS;
파티션 키 값에 : 나 공백을 넣지 않는 편이 낫다. 시각까지 파티션으로 나눠야 하면 dt=20221111/hh=15 처럼 키를 나누거나 dt=2022-11-11-1511 처럼 구분자를 바꾼다. 이스케이프된 경로는 이 문서의 혼선 말고도 쉘 인용, Spark 의 경로 파싱, 외부 도구의 URL 처리에서 반복해서 문제를 일으킨다.