UNKNOWN 데이터 타입

UNKNOWN 데이터 타입 (UNKNOWN data type)

Snowflake의 UNKNOWN 데이터 타입을 다루는 문서예요. UNKNOWN은 Apache Iceberg™ v3 원시 타입으로, 아직 타입이 알려지지 않은 열이나 필드를 정의하는 데 사용해요. UNKNOWN 열/필드는 물리적 저장 공간이 없고 항상 NULL로 읽힌다는 특징이 있어요. 지정 방법, 읽기·쓰기, 로딩/언로딩, 스키마 진화와 제한 사항을 확인할 수 있어요.

출처: Snowflake SQL Reference

본문

이 문서는 UNKNOWN 데이터 타입을 설명해요.

UNKNOWN

UNKNOWN 데이터 타입은 Apache Iceberg™ v3 원시 타입이에요. 아직 타입이 알려지지 않은 열이나 필드를 정의하는 데 사용해요.

UNKNOWN 열 또는 필드에는 다음 특성이 있어요.

  • 기본 Parquet 데이터 파일에 물리적 저장 공간이 없어요.
  • 모든 행에 대해 항상 NULL로 읽혀요.
  • 항상 nullable이에요. NOT NULL 제약을 적용할 수 없어요.
  • 여기에 값을 쓸 수 없어요.

UNKNOWN 타입은 Iceberg 포맷 버전 3(ICEBERG_VERSION = 3)을 사용하는 Apache Iceberg 테이블(Snowflake 관리형과 외부 관리형 모두)에서만 지원돼요. 표준 Snowflake 테이블에서는 지원되지 않아요.

UNKNOWN 열 또는 필드 지정하기

UNKNOWN 열을 정의하려면 CREATE ICEBERG TABLE 문에서 열 타입으로 UNKNOWN 키워드를 사용해요.

CREATE ICEBERG TABLE my_iceberg_table (c1 INT, c2 UNKNOWN, c3 INT)
  CATALOG = 'SNOWFLAKE'
  EXTERNAL_VOLUME = 'my_external_volume'
  BASE_LOCATION = 'my_iceberg_table'
  ICEBERG_VERSION = 3;

정형 OBJECT 안의 필드 타입으로도 UNKNOWN을 사용할 수 있어요.

CREATE ICEBERG TABLE my_iceberg_table (c1 INT, c2 OBJECT(f1 INT, f2 UNKNOWN, f3 INT))
  CATALOG = 'SNOWFLAKE'
  EXTERNAL_VOLUME = 'my_external_volume'
  BASE_LOCATION = 'my_iceberg_table'
  ICEBERG_VERSION = 3;

UNKNOWN은 ARRAY의 요소 타입이나 MAP의 키/값 타입으로는 지원되지 않아요. 다음 정의는 거부돼요.

ARRAY(UNKNOWN)
MAP(UNKNOWN, VARCHAR)
MAP(VARCHAR, UNKNOWN)

UNKNOWN 열과 필드 읽기

UNKNOWN 열에는 저장 공간이 없으므로 항상 NULL을 반환해요.

SELECT c1, c2, c3 FROM my_iceberg_table;
+----+------+----+
| C1 | C2   | C3 |
|----+------+----|
|  1 | NULL | 10 |
|  2 | NULL | 20 |
+----+------+----+

UNKNOWN 필드를 포함하는 정형 OBJECT를 읽으면, 필드는 결과에 존재하고 그 값은 NULL이에요. 예를 들어 OBJECT(f1 INT, f2 UNKNOWN, f3 INT)로 정의된 열을 읽으면 다음과 같이 반환돼요.

{
  "f1": 1,
  "f2": null,
  "f3": 3
}

집계 함수는 UNKNOWN 열을 NULL로 취급해요.

  • COUNT(*)는 모든 행을 센다.
  • COUNT(<unknown_column>)0을 반환한다.
  • MIN, MAX, SUM, AVGNULL을 반환한다.
  • GROUP BY는 UNKNOWN 열의 모든 행을 단일 NULL 그룹으로 묶는다.

경로 구문으로 UNKNOWN 필드 추출하기

정형 OBJECT에서 경로 표기법(path notation)(예: my_object_column:my_unknown_field)으로 UNKNOWN 필드를 추출하면, 필드에 저장된 값이 없으므로 NULL을 반환해요.

UNKNOWN 열과 필드에 쓰기

UNKNOWN 열이나 필드에는 값을 쓸 수 없어요. 항상 NULL로 유지돼요. UNKNOWN이 포함된 테이블에 쓰는 방법은 UNKNOWN이 최상위 열인지 정형 OBJECT 안의 필드인지에 따라 달라져요.

최상위 UNKNOWN 열 (Top-level UNKNOWN columns)

UNKNOWN 열을 직접 대상으로 하는 INSERT, UPDATE, MERGE 연산은 오류와 함께 실패해요. 행을 쓸 때 열 목록에서 UNKNOWN 열은 생략해요. 나머지 열은 평소처럼 채워져요.

INSERT INTO my_iceberg_table (c1, c3) VALUES (1, 10);

정형 객체 안의 UNKNOWN 필드 (UNKNOWN fields inside structured objects)

UNKNOWN 필드를 포함하는 정형 OBJECT 열에 쓰려면, 필드 이름·순서·강제 변환 가능한 타입이 일치하는 non-UNKNOWN 필드만 포함하는 소스 객체를 제공해요. UNKNOWN 필드는 자동으로 NULL로 저장돼요. 예를 들어 c2 OBJECT(f1 INT, f2 UNKNOWN, f3 INT)로 정의된 열이 주어졌을 때:

INSERT INTO my_iceberg_table (c2)
  SELECT OBJECT_CONSTRUCT('f1', 1, 'f3', 3)::OBJECT(f1 INT, f3 INT);

UPDATE my_iceberg_table
  SET c2 = OBJECT_CONSTRUCT('f1', 10, 'f3', 30)::OBJECT(f1 INT, f3 INT);

추가 필드를 넣거나 대상 스키마와 일치하지 않는 필드 이름을 사용하는 소스 객체를 제공하면 오류가 발생해요.

데이터 로딩과 언로딩 (Loading and unloading data)

COPY INTO

로 UNKNOWN 열이나 필드가 있는 Iceberg 테이블에 데이터를 로딩할 때, 소스 파일은 그 열과 필드를 생략해야 해요. 물리적 저장 공간이 없기 때문이에요. 로딩 후 UNKNOWN 열과 필드는 NULL로 다시 읽혀요. 예를 들어 t (a INT, b STRING, c UUID, u UNKNOWN)로 정의된 테이블에 로딩할 때는 a, b, c에만 값을 제공하고 uNULL로 다시 읽혀요.

COPY INTO 로 데이터를 언로딩할 때, UNKNOWN 열은 NULL로 내보내져요.

UNKNOWN 열 진화시키기 (Evolving an UNKNOWN column)

스키마 진화(schema evolution)를 통해 UNKNOWN 열을 어떤 원시 타입으로든 진화시킬 수 있어요.

ALTER ICEBERG TABLE my_iceberg_table ALTER COLUMN c2 SET DATA TYPE INT;

UNKNOWN 열을 정형 타입(ARRAY, OBJECT, MAP)으로 직접 진화시킬 수는 없어요.

CREATE TABLE AS SELECT와 쿼리 결과

CREATE TABLE

AS SELECT를 최상위 UNKNOWN 열을 선택하는 쿼리와 함께 사용하면, 결과 열의 타입은 대상 테이블에 따라 달라져요.

  • 대상이 Iceberg v3 테이블이면 UNKNOWN 열은 UNKNOWN으로 보존돼요.
  • 대상이 UNKNOWN을 저장할 수 없는 표준 Snowflake 테이블이면, UNKNOWN 열은 NULL을 포함하는 nullable VARCHAR 열로 변환돼요. 최상위 UNKNOWN 열은 결과 메타데이터에서도 VARCHAR로 보고돼요.

UNKNOWN 필드를 포함하는 정형 타입 열(ARRAY, OBJECT, MAP)을 선택하는 쿼리로는 CREATE TABLE AS SELECT를 사용할 수 없어요. 이 연산은 오류를 반환해요.

UNKNOWN 데이터 타입 예제 (Examples)

UNKNOWN 열이 있는 관리형 Iceberg 테이블을 만들고, 행을 삽입하고, 열을 NULL로 다시 읽어요.

CREATE ICEBERG TABLE t (c1 INT, c2 UNKNOWN, c3 INT)
  CATALOG = 'SNOWFLAKE'
  EXTERNAL_VOLUME = 'my_external_volume'
  BASE_LOCATION = 't'
  ICEBERG_VERSION = 3;

INSERT INTO t (c1, c3) VALUES (1, 10), (2, 20);

SELECT * FROM t;
+----+------+----+
| C1 | C2   | C3 |
|----+------+----|
|  1 | NULL | 10 |
|  2 | NULL | 20 |
+----+------+----+

나중에 UNKNOWN 열을 구체적인 타입으로 승격시켜요.

ALTER ICEBERG TABLE t ALTER COLUMN c2 SET DATA TYPE VARCHAR;

UNKNOWN 데이터 타입의 제한 사항 (Limitations for the UNKNOWN data type)

  • UNKNOWN은 ICEBERG_VERSION = 3을 사용하는 Iceberg 테이블에서만 지원돼요. 표준 Snowflake 테이블에서는 지원되지 않아요.
  • UNKNOWN 열이나 필드는 항상 nullable이며 NOT NULL 제약을 받을 수 없어요.
  • UNKNOWN 열이나 필드에 값을 쓸 수 없어요.
  • UNKNOWN은 ARRAY 요소 타입이나 MAP 키/값 타입으로 허용되지 않아요.
  • UNKNOWN 열은 원시 타입으로만 진화시킬 수 있고 정형 타입으로는 진화시킬 수 없어요.
  • UNKNOWN은 사용자 정의 함수(UDF), 사용자 정의 테이블 함수(UDTF), 저장 프로시저에서 지원되지 않아요.

더 알아보기 (Learn more)