Variant(T1, T2, ..., TN) 타입은 이 타입의 각 행이 T1, T2, …, TN 중 하나의 타입 값을 가지거나, 어느 타입에도 해당하지 않는 NULL 값을 가질 수 있음을 의미합니다.
중첩된 타입의 순서는 중요하지 않습니다. 즉, Variant(T1, T2) = Variant(T2, T1)입니다.
중첩된 타입은 Nullable(…), LowCardinality(Nullable(…)), Variant(…) 타입을 제외하면 어떤 타입이든 사용할 수 있습니다.
유사한 타입을 variant로 사용하는 것은 권장되지 않습니다(예:
Variant(UInt32, Int64)처럼 서로 다른 숫자 타입이나 Variant(Date, DateTime)처럼 서로 다른 날짜 타입).
이러한 타입의 값을 처리할 때 모호성이 발생할 수 있기 때문입니다. 기본적으로 이런 Variant 타입을 생성하면 예외가 발생하지만, 설정 allow_suspicious_variant_types를 사용해 활성화할 수 있습니다.Variant 생성하기
Variant 타입을 사용하는 방법:
if/multiIf 함수를 사용합니다(use_variant_as_common_type 설정이 활성화되어 있어야 함):
use_variant_as_common_type 설정이 활성화되어 있어야 합니다):
Variant 중첩 타입을 서브컬럼으로 읽기
variant Variant(T1, T2, T3) 컬럼이 있으면 variant.T2 구문을 사용해 T2 타입의 서브컬럼을 읽을 수 있습니다.
이 서브컬럼의 타입은 T2가 Nullable 안에 포함될 수 있으면 Nullable(T2)이고, 그렇지 않으면 T2입니다. 또한 이 서브컬럼은
원래 Variant 컬럼과 동일한 크기를 가지며, 원래 Variant 컬럼의 타입이 T2가 아닌 모든 행에는 NULL 값(T2가 Nullable 안에 포함될 수 없으면 빈 값)이 들어갑니다.
Variant 서브컬럼은 variantElement(variant_column, type_name) 함수를 사용해서도 읽을 수 있습니다.
예시:
variantType(variant_column) 함수를 사용할 수 있습니다. 이 함수는 각 행의 variant 유형 이름을 나타내는 Enum을 반환합니다(NULL인 행은 'None').
예시:
Variant 컬럼과 다른 컬럼 사이의 변환
Variant 타입의 컬럼에 대해 수행할 수 있는 변환은 4가지입니다.
String 컬럼을 Variant 컬럼으로 변환하기
String에서 Variant로의 변환은 문자열 값을 파싱해 Variant 타입의 값을 추출하는 방식으로 수행됩니다:
String에서 Variant로 변환할 때 파싱을 비활성화하려면 cast_string_to_dynamic_use_inference 설정을 비활성화하면 됩니다:
일반 컬럼을 Variant 컬럼으로 변환하기
T인 일반 컬럼은 해당 타입을 포함하는 Variant 컬럼으로 변환할 수 있습니다:
String 타입에서의 변환은 항상 파싱을 거쳐 수행됩니다. 파싱 없이 String 컬럼을 Variant의 String 대안으로 변환해야 하는 경우, 다음과 같이 할 수 있습니다:
Variant 컬럼을 일반 컬럼으로 변환하기
Variant 컬럼은 일반 컬럼으로 변환할 수 있습니다. 이 경우 모든 중첩된 variant가 대상 타입으로 변환됩니다:
Variant를 다른 Variant로 변환하기
Variant 컬럼은 다른 Variant 컬럼으로 변환할 수 있지만, 대상 Variant 컬럼에 원래 Variant의 모든 중첩 타입이 포함된 경우에만 가능합니다:
데이터에서 Variant 타입 읽기
Variant 타입을 읽을 수 있습니다. 데이터를 파싱하는 동안 ClickHouse는 값을 가장 적합한 Variant 타입으로 삽입하려고 시도합니다.
예시:
Variant 타입 값 비교
Variant 타입의 값은 동일한 Variant 타입의 값과만 비교할 수 있습니다.
기본적으로 비교 연산자는 Variant의 기본 구현을 사용하여
각 variant type에 대해 개별적으로 비교를 수행합니다. 이는 setting use_variant_default_implementation_for_comparisons = 0을 사용해 비활성화할 수 있으며,
이 경우 아래에 설명된 네이티브 Variant 비교 규칙이 사용됩니다. 참고: ORDER BY는 항상 네이티브 비교를 사용합니다.
네이티브 Variant 비교 규칙:
타입 Variant(..., T1, ... T2, ...)에서 내부 타입이 T1인 값 v1과 내부 타입이 T2인 값 v2에 대한 연산자 <의 결과는 다음과 같이 정의됩니다.
T1 = T2 = T이면 결과는v1.T < v2.T입니다(내부 값이 비교됩니다).T1 != T2이면 결과는T1 < T2입니다(타입 이름이 비교됩니다).
Variant 값을 가진 행을 찾아야 한다면, 다음 방법 중 하나를 사용할 수 있습니다:
- 값을 해당
Variant유형으로 CAST합니다:
Variant서브컬럼을 필요한 타입과 비교합니다:
Array/Map/Tuple 같은 복합 타입의 서브컬럼은 Nullable 안에 포함될 수 없으며, 타입이 다른 행에서는 NULL 대신 기본값을 가지므로, 경우에 따라 variant 타입에 추가 검사를 수행하는 것이 유용할 수 있습니다:
Variant 타입은 GROUP BY/ORDER BY 키로 사용할 수 없습니다. 사용하려면 이 타입의 특수한 비교 규칙을 고려하고 allow_suspicious_types_in_group_by/allow_suspicious_types_in_order_by 설정을 활성화하십시오.
Variant를 지원하는 JSONExtract 함수
JSONExtract* 함수는 Variant 타입을 지원합니다.
Variant 인수를 사용하는 함수
Variant 타입 인수를 자동으로 지원합니다.
26.1 버전부터는 Variant 타입을 명시적으로 처리하지 않는 함수에 Variant 컬럼이 전달되면 ClickHouse는 다음을 수행합니다:
- Variant 컬럼에서 각 변형 타입을 추출합니다
- 각 변형 타입에 대해 함수를 개별적으로 실행합니다
- 결과 타입에 따라 결과를 적절히 결합합니다
-
서로 다른 결과 타입:
Variant(T1, T2, ...) -
타입 비호환성: 호환되지 않는 variant에는
NULL
오류 처리: 함수가 variant 타입을 처리할 수 없을 때는 타입 관련 오류(ILLEGAL_TYPE_OF_ARGUMENT,
TYPE_MISMATCH, CANNOT_CONVERT_TYPE, NO_COMMON_TYPE)만 포착되며, 해당 행의 결과는 NULL이 됩니다. 그 밖의 오류(예:
0으로 나누기, 메모리 부족)는 실제 문제를 조용히 숨기지 않도록 평소처럼 그대로 발생합니다.
유형 불일치 시 동작
variant_throw_on_type_mismatch는 함수가 Variant 컬럼에 적용될 때, 행에 실제로 저장된 유형이 해당 함수와 호환되지 않으면 어떻게 처리할지를 제어합니다:
true(기본값) — 처음으로 호환되지 않는 행에서 예외(ILLEGAL_TYPE_OF_ARGUMENT)를 발생시킵니다.false— 호환되지 않는 행에는NULL을 반환하고, 호환되는 행은 결과를 유지합니다.