외부 테이블에 제약 조건을 붙이면 Hive 가 거부한다.
FAILED: SemanticException Invalid Constraint syntax
Constraints are disallowed with External tables
Hive 는 관리 테이블에 한해 PRIMARY KEY · FOREIGN KEY · UNIQUE · NOT NULL · DEFAULT · CHECK 를 선언할 수 있게 하지만, 외부 테이블에는 이를 허용하지 않는다. 외부 테이블의 데이터는 Hive 가 소유하지 않으므로 어떤 조건도 보장할 수 없기 때문이다.
Hive 의 제약 조건은 관계형 DB 처럼 쓰기를 막는 장치가 아니다. 크게 두 갈래로 나뉜다.
NOT NULL · DEFAULT · CHECK 는 관리 테이블에 대해 실제로 강제된다. 위반하는 INSERT 는 실패한다.
PRIMARY KEY · FOREIGN KEY · UNIQUE 는 강제되지 않는다. 옵티마이저에게 알려 주는 선언일 뿐이라 DISABLE NOVALIDATE 를 붙여야 하고, 실제로 중복 값을 넣어도 막히지 않는다. RELY 를 추가로 붙이면 옵티마이저가 그 선언을 믿고 조인 제거 같은 변형을 수행한다 — 값이 실제로 그 조건을 만족하지 않으면 잘못된 결과가 나온다.
CREATE TABLE managed_tbl (
id BIGINT,
name STRING NOT NULL,
dept STRING,
PRIMARY KEY (id) DISABLE NOVALIDATE RELY
)
STORED AS ORC
TBLPROPERTIES ('transactional'='true');
제약이 실제로 필요하면 관리 테이블로 만든다. 외부 테이블을 쓰는 이유가 파일 위치를 Hive 밖에서 관리하기 위해서라면, LOCATION 을 지정한 관리 테이블로도 위치는 원하는 곳에 둘 수 있다. 다만 관리 테이블은 DROP TABLE 시 데이터도 함께 지워지므로 그 차이를 감수해야 한다.
CREATE TABLE tbl (id BIGINT, name STRING NOT NULL)
STORED AS ORC
LOCATION '/warehouse/custom/tbl';
제약이 문서화 목적이면 주석으로 남긴다. 어차피 강제되지 않는 선언을 위해 테이블 종류를 바꾸는 것은 얻는 것이 없다.
CREATE EXTERNAL TABLE ext_tbl (
id BIGINT COMMENT '논리적 기본 키. Hive 가 강제하지 않는다',
name STRING
)
STORED AS PARQUET
LOCATION '/data/ext_tbl';
데이터 품질 보장이 목적이면 적재 파이프라인에서 검증한다. NULL 검사나 중복 검사를 적재 직후 쿼리로 수행하고 위반 건을 별도 테이블에 남기는 방식이 실질적이다.
SELECT COUNT(*) FROM ext_tbl WHERE id IS NULL;
SELECT id, COUNT(*) c FROM ext_tbl GROUP BY id HAVING c > 1;
Hive 3 부터 CREATE TABLE 의 기본이 배포판 설정에 따라 외부 테이블이 되는 경우가 있다. EXTERNAL 을 적지 않았는데 이 오류가 나면 기본값을 확인한다.
SET hive.create.as.external.legacy;
DESCRIBE FORMATTED tbl;
Table Type 이 EXTERNAL_TABLE 이면 외부 테이블이다.