Oracle 에서 읽어 Hive 테이블로 CTAS 할 때 나는 오류다.
incorrect timestamp precision for timestamp(0); the configured precision is milliseconds; column name: initdttm
단순 SELECT 는 되는데 CREATE TABLE ... AS SELECT 에서만 실패한다.
Trino 의 timestamp 타입은 정밀도를 갖는다. timestamp(0) 은 초까지, timestamp(3) 은 밀리초까지다. Oracle 의 TIMESTAMP(0) 컬럼은 Trino 에서 timestamp(0) 으로 읽힌다.
한편 Hive 커넥터는 쓰기 시 다룰 정밀도를 hive.timestamp-precision 으로 고정해 두고 있고 기본값이 MILLISECONDS, 즉 timestamp(3) 이다. CTAS 는 SELECT 결과의 타입을 그대로 대상 테이블 컬럼 타입으로 삼으므로 timestamp(0) 컬럼을 만들려 하고, Hive 커넥터가 이를 거부한다. 컬럼 타입을 사람이 미리 지정하는 CREATE TABLE + INSERT 에서는 이 충돌이 생기지 않는다.
가장 간단하고 부작용이 없다. 문제가 되는 컬럼만 대상 정밀도로 맞춘다.
CREATE TABLE hive.sales.orders AS
SELECT
order_id,
customer,
CAST(initdttm AS timestamp(3)) AS initdttm,
CAST(updttm AS timestamp(3)) AS updttm
FROM oracle.sales.orders;
timestamp(0) 값을 timestamp(3) 으로 올려도 값은 그대로이고 소수부만 .000 이 된다. 반대로 내리면 잘리므로 방향을 확인한다. 어떤 컬럼이 문제인지 모르겠다면 원본 쪽 타입을 먼저 본다.
SELECT typeof(initdttm) FROM oracle.sales.orders LIMIT 1;
컬럼이 많아 CAST 를 일일이 쓰기 번거롭거나, 대상 테이블의 포맷·파티션을 정확히 통제하고 싶을 때 쓴다.
CREATE TABLE hive.sales.orders (
order_id bigint,
customer varchar,
initdttm timestamp(3),
updttm timestamp(3)
)
WITH (format = 'PARQUET');
INSERT INTO hive.sales.orders
SELECT order_id, customer, initdttm, updttm
FROM oracle.sales.orders;
INSERT 는 대상 컬럼 타입으로 암묵 변환하므로 CAST 없이도 들어간다.
카탈로그 속성으로 커넥터가 다룰 정밀도를 올릴 수 있다.
hive.timestamp-precision=MICROSECONDS
쓸 수 있는 값은 MILLISECONDS(기본) · MICROSECONDS · NANOSECONDS 세 가지다. SECONDS 는 없다. timestamp(0) 에 맞추려고 SECONDS 를 넣으면 잘못된 설정값이라며 기동이 실패한다. 정밀도를 올리는 방향은 되지만 내리는 방향은 이 설정으로 해결되지 않는다.
이 값은 카탈로그 전체에 적용되고 이미 만들어진 테이블의 해석에도 영향을 주므로, 한 쿼리를 통과시키려고 바꾸는 것은 권하지 않는다. 설정보다 CAST 가 먼저다.
Oracle 커넥터에는 정밀도를 강제로 올려 주는 설정이 없다. 원본이 TIMESTAMP(0) 이면 Trino 에서도 timestamp(0) 이다. 값에 .000 이 보인다고 해서 원본 타입이 TIMESTAMP(3) 이라는 뜻은 아니며, 클라이언트가 출력 형식을 맞춰 보여 준 것일 수 있다.
Trino 카탈로그·스키마와 CTAS · Trino Oracle 커넥터에서 NUMBER 컬럼이 보이지 않는 문제