Kudu 테이블에 없는 파티션 값이나 중복 기본키를 넣으면, 해당 행만 버려지고 문장은 성공으로 끝난다.
Modified 0 row(s), 1 row error(s) in 0.15s
impala-shell 의 종료 코드는 0 이고 JDBC 도 예외를 던지지 않는다. 배치가 "성공"으로 기록되면서 데이터만 빠지는 것이 이 문제의 위험한 점이다.
Kudu DML 에서 행 단위 거부(제약 위반, 없는 range 파티션, 기본키 중복)는 경고로 처리된다. Impala 에는 경고를 오류로 승격시키는 질의 옵션이 없다. INSERT ... IGNORE 를 붙이든 안 붙이든 없는 파티션 문제는 그대로 남는다.
Kudu 는 Hive/HDFS 파티션 테이블과 달리 동적으로 파티션을 만들지 않는다. range 파티션은 미리 정의돼 있어야 하고, 정의된 범위 밖의 값은 저장되지 않는다. Hive 의 default partition(__HIVE_DEFAULT_PARTITION__) 같은 수용 공간도 없다.
적재 결과 문자열을 검사해 바깥에서 실패로 만든다.
#!/bin/bash
SQL="INSERT INTO db.tbl SELECT * FROM db.stg"
out=$(impala-shell -i coord.example.com:21050 --ssl -k -q "$SQL" 2>&1)
rc=$?
echo "$out"
[ $rc -ne 0 ] && exit 1
err=$(echo "$out" | sed -nE 's/.*[^0-9]([0-9]+) row error\(s\).*/\1/p' | tail -1)
if [ -n "$err" ] && [ "$err" -gt 0 ]; then
echo "row error ${err}건 — 실패 처리"
exit 1
fi
JDBC 로 실행한다면 Statement.getWarnings() 로 경고를 받아 같은 판단을 한다.
더 나은 방법은 넣기 전에 확인하는 것이다. 현재 정의된 range 를 보고, 벗어나는 건수를 세어 둔다.
SHOW RANGE PARTITIONS db.tbl;
SELECT count(*) FROM db.stg s
WHERE NOT EXISTS (SELECT 1 FROM db.tbl t WHERE t.part_col = s.part_col);
필요한 파티션을 미리 추가한다.
ALTER TABLE db.tbl ADD RANGE PARTITION '20260301' <= VALUES < '20260401';
스테이징 테이블에 먼저 적재하고, 유효한 값만 본 테이블로 옮기는 2단계 구성이 가장 안전하다. 버려진 행은 그대로 스테이징에 남아 원인 분석이 가능하다.