NumericIndexedVector는 벡터를 캡슐화하며 벡터 집계와 원소별 연산을 지원하는 추상 데이터 구조입니다. 저장 방식으로는 Bit-Sliced Index를 사용합니다. 이론적 배경과 사용 시나리오는 논문 Large-Scale Metric Computation in Online Controlled Experiment Platform을 참고하십시오.
BSI
BSI(Bit-Sliced Index) 저장 방식에서는 데이터를 Bit-Sliced Index 형태로 저장한 다음 Roaring Bitmap으로 압축합니다. 집계 연산과 원소별 연산은 압축된 데이터에 직접 수행되므로 저장 및 쿼리 효율을 크게 높일 수 있습니다.
벡터는 인덱스와 그에 대응하는 값으로 구성됩니다. 다음은 BSI 저장 모드에서 이 데이터 구조가 갖는 몇 가지 특성과 제약 사항입니다:
- 인덱스 타입은
UInt8,UInt16,UInt32중 하나일 수 있습니다. 참고: Roaring Bitmap의 64비트 구현 성능을 고려하면, BSI 포맷은UInt64/Int64를 지원하지 않습니다. - 값 타입은
Int8,Int16,Int32,Int64,UInt8,UInt16,UInt32,UInt64,Float32,Float64중 하나일 수 있습니다. 참고: 값 타입은 자동으로 확장되지 않습니다. 예를 들어 값 타입으로UInt8을 사용하는 경우,UInt8의 표현 범위를 초과하는 합계는 더 큰 타입으로 승격되지 않고 오버플로우가 발생합니다. 마찬가지로 정수 연산은 정수 결과를 반환합니다(예: 나눗셈이 자동으로 부동소수점 결과로 변환되지 않음). 따라서 값 타입은 미리 충분히 검토하여 설계하는 것이 중요합니다. 실제 환경에서는 부동소수점 타입(Float32/Float64)이 일반적으로 사용됩니다. - 연산은 인덱스 타입과 값 타입이 모두 같은 두 벡터 사이에서만 수행할 수 있습니다.
- 하위 저장소는 Bit-Sliced Index를 사용하며, 비트맵이 인덱스를 저장합니다. 비트맵의 구체적인 구현으로는 Roaring Bitmap이 사용됩니다. 압축률과 쿼리 성능을 극대화하려면 인덱스를 가능한 한 소수의 Roaring Bitmap 컨테이너에 집중시키는 것이 좋습니다.
- Bit-Sliced Index 메커니즘은 값을 이진수로 변환합니다. 부동소수점 타입의 경우 이 변환에는 고정소수점 표현이 사용되므로 정밀도 손실이 발생할 수 있습니다. 정밀도는 소수부에 사용할 비트 수를 사용자 지정해 조정할 수 있으며, 기본값은 24비트로 대부분의 시나리오에서 충분합니다.
-State와 함께 집계 함수 groupNumericIndexedVector를 사용해 NumericIndexedVector를 생성할 때 정수부와 소수부의 비트 수를 사용자 지정할 수 있습니다. - 인덱스에는 0이 아닌 값, 0 값, 존재하지 않는 값의 세 가지 경우가 있습니다. NumericIndexedVector에는 0이 아닌 값과 0 값만 저장됩니다. 또한 두 NumericIndexedVector 사이의 원소별 연산에서는 존재하지 않는 인덱스의 값을 0으로 간주합니다. 나눗셈에서는 제수가 0이면 결과는 0입니다.
numericIndexedVector 객체 만들기
이 구조를 만드는 방법은 두 가지입니다. 하나는 집계 함수 groupNumericIndexedVector에 -State를 사용해 만드는 것입니다.
추가 조건을 받도록 접미사 -if를 붙일 수 있습니다.
집계 함수는 해당 조건을 충족하는 행만 처리합니다.
다른 하나는 numericIndexedVectorBuild를 사용해 맵으로부터 빌드하는 것입니다.
groupNumericIndexedVectorState 함수는 매개변수를 통해 정수 비트 수와 소수 비트 수를 사용자 지정할 수 있지만, numericIndexedVectorBuild는 그렇지 않습니다.
groupNumericIndexedVector
두 개의 데이터 컬럼에서 NumericIndexedVector를 생성하고, 모든 값의 합을 Float64 유형으로 반환합니다. 접미사 State를 추가하면 NumericIndexedVector 객체를 반환합니다.
구문
groupNumericIndexedVectorState(col1, col2)
groupNumericIndexedVectorState(type, integer_bit_num, fraction_bit_num)(col1, col2)매개변수
type: String, 선택 사항. 저장 포맷을 지정합니다. 현재는'BSI'만 지원합니다.integer_bit_num:UInt32, 선택 사항.'BSI'저장 포맷에서만 적용되며, 정수 부분에 사용하는 비트 수를 나타냅니다. 인덱스 타입이 정수 타입인 경우 기본값은 해당 인덱스를 저장하는 데 사용되는 비트 수와 같습니다. 예를 들어 인덱스 타입이 UInt16이면 기본integer_bit_num값은 16입니다. Float32 및 Float64 인덱스 타입의 경우integer_bit_num의 기본값은 40이므로, 표현할 수 있는 데이터의 정수 부분 범위는[-2^39, 2^39 - 1]입니다. 허용 범위는[0, 64]입니다.fraction_bit_num:UInt32, 선택 사항.'BSI'저장 포맷에서만 적용되며, 소수 부분에 사용하는 비트 수를 나타냅니다. 값 타입이 정수이면 기본값은 0이고, 값 타입이 Float32 또는 Float64이면 기본값은 24입니다. 허용 범위는[0, 24]입니다.- 또한 integer_bit_num + fraction_bit_num의 허용 범위는 [0, 64]여야 합니다.
col1: 인덱스 컬럼입니다. 지원되는 타입:UInt8/UInt16/UInt32/Int8/Int16/Int32.col2: 값 컬럼입니다. 지원되는 타입:Int8/Int16/Int32/Int64/UInt8/UInt16/UInt32/UInt64/Float32/Float64.
반환 값
모든 값의 합계를 나타내는 Float64 값입니다.
예시
테스트 데이터:
UserID PlayTime
1 10
2 20
3 30쿼리 & 결과:
SELECT groupNumericIndexedVector(UserID, PlayTime) AS num FROM t;
┌numericIndexedVectorAllValueSum
v25.7.0에서 도입
numericIndexedVector에 있는 모든 값의 합계를 반환합니다.
구문
numericIndexedVectorAllValueSum(v)인수
반환 값
합을 반환합니다. Float64
예시
사용 예시
SELECT numericIndexedVectorAllValueSum(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;┌─res─┐
│ 60 │
└─────┘numericIndexedVectorBuild
도입: v25.7.0
맵에서 NumericIndexedVector를 생성합니다. 맵의 키는 벡터의 인덱스를, 맵의 값은 벡터의 값을 나타냅니다.
구문
numericIndexedVectorBuild(map)인수
map— 인덱스를 값에 매핑한 것입니다.Map
반환 값
NumericIndexedVector 객체를 반환합니다. AggregateFunction
예시
사용 예시
-- A NumericIndexedVector is a binary value, so it is shown with `hex`.
SELECT
hex(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res,
toTypeName(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS type;┌─res────────────────────────────────────────────────────────────────┬─type───────────────────────────────────────────────────────┐
│ 080000000000000001010000020103000002020300000201030000020203010101 │ AggregateFunction(groupNumericIndexedVector, UInt8, UInt8) │
└────────────────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘numericIndexedVectorCardinality
도입 버전: v25.7.0
numericIndexedVector의 기수(고유 인덱스 개수)를 반환합니다.
구문
numericIndexedVectorCardinality(v)인수
반환 값
고유한 인덱스 개수를 반환합니다. UInt64
예시
사용 예시
SELECT numericIndexedVectorCardinality(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;┌─res─┐
│ 3 │
└─────┘numericIndexedVectorGetValue
도입 버전: v25.7.0
numericIndexedVector에서 지정한 인덱스에 해당하는 값을 반환합니다.
구문
numericIndexedVectorGetValue(v, i)인수
v—numericIndexedVectori— 값을 조회할 인덱스입니다.(U)Int*
반환 값
NumericIndexedVector의 값 타입과 동일한 타입의 숫자 값입니다. (U)Int* 또는 Float*
예시
사용 예시
SELECT numericIndexedVectorGetValue(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30])), 3) AS res;┌─res─┐
│ 30 │
└─────┘numericIndexedVectorPointwiseAdd
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 덧셈을 수행합니다.
구문
numericIndexedVectorPointwiseAdd(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
WITH
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseAdd(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseAdd(vec1, 2)) AS res2;┌─res1──────────────────┬─res2─────────────┐
│ {1:10,2:30,3:50,4:30} │ {1:12,2:22,3:32} │
└───────────────────────┴──────────────────┘numericIndexedVectorPointwiseDivide
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 나눗셈을 수행합니다.
구문
numericIndexedVectorPointwiseDivide(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseDivide(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseDivide(vec1, 2)) AS res2;┌─res1────────────────┬─res2────────────┐
│ {1:0,2:2,3:1.5,4:0} │ {1:5,2:10,3:15} │
└─────────────────────┴─────────────────┘numericIndexedVectorPointwiseEqual
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간의 원소별 비교를 수행합니다. 결과는 값이 같은 인덱스를 포함하는 numericIndexedVector이며, 해당 인덱스의 모든 값은 1로 설정됩니다.
구문
numericIndexedVectorPointwiseEqual(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseEqual(vec1, 20)) AS res2;┌─res1──┬─res2──┐
│ {2:1} │ {2:1} │
└───────┴───────┘numericIndexedVectorPointwiseGreater
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 비교를 수행합니다. 결과는 첫 번째 벡터의 값이 두 번째 벡터의 값보다 큰 인덱스를 포함하는 numericIndexedVector이며, 해당 값은 모두 1로 설정됩니다.
구문
numericIndexedVectorPointwiseGreater(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 50]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreater(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreater(vec1, 20)) AS res2;┌─res1──────┬─res2──┐
│ {1:1,3:1} │ {3:1} │
└───────────┴───────┘numericIndexedVectorPointwiseGreaterEqual
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 비교를 수행합니다. 결과는 첫 번째 벡터의 값이 두 번째 벡터의 값보다 크거나 같은 인덱스를 포함하는 numericIndexedVector이며, 해당 값은 모두 1로 설정됩니다.
구문
numericIndexedVectorPointwiseGreaterEqual(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새로운 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 50]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreaterEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseGreaterEqual(vec1, 20)) AS res2;┌─res1──────────┬─res2──────┐
│ {1:1,2:1,3:1} │ {2:1,3:1} │
└───────────────┴───────────┘numericIndexedVectorPointwiseLess
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 사이에서 원소별 비교를 수행합니다. 결과는 첫 번째 벡터의 값이 두 번째 벡터의 값보다 작은 인덱스를 포함하는 numericIndexedVector이며, 해당 값은 모두 1로 설정됩니다.
구문
numericIndexedVectorPointwiseLess(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseLess(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseLess(vec1, 20)) AS res2;┌─res1──────┬─res2──┐
│ {3:1,4:1} │ {1:1} │
└───────────┴───────┘numericIndexedVectorPointwiseLessEqual
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 비교를 수행합니다. 결과는 첫 번째 벡터의 값이 두 번째 벡터의 값보다 작거나 같은 인덱스를 포함하는 numericIndexedVector이며, 해당 인덱스의 모든 값은 1로 설정됩니다.
구문
numericIndexedVectorPointwiseLessEqual(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는(U)Int*,Float*,numericIndexedVector타입의 numericIndexedVector 객체
반환 값
새로운 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 40, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseLessEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseLessEqual(vec1, 20)) AS res2;┌─res1──────────┬─res2──────┐
│ {2:1,3:1,4:1} │ {1:1,2:1} │
└───────────────┴───────────┘numericIndexedVectorPointwiseMultiply
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 곱셈을 수행합니다.
구문
numericIndexedVectorPointwiseMultiply(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새로운 numericIndexedVector 객체를 반환합니다.
예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toInt32(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toInt32(x), [10, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseMultiply(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseMultiply(vec1, 2)) AS res2;┌─res1──────────────────┬─res2─────────────┐
│ {1:0,2:200,3:600,4:0} │ {1:20,2:40,3:60} │
└───────────────────────┴──────────────────┘numericIndexedVectorPointwiseNotEqual
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 비교를 수행합니다. 결과는 값이 서로 같지 않은 인덱스를 포함하는 numericIndexedVector이며, 해당하는 모든 값은 1로 설정됩니다.
구문
numericIndexedVectorPointwiseNotEqual(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는 numericIndexedVector 객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
with
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toFloat64(x), [10, 20, 30]))) as vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toFloat64(x), [20, 20, 30]))) as vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseNotEqual(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseNotEqual(vec1, 20)) AS res2;┌─res1──────────┬─res2──────┐
│ {1:1,3:1,4:1} │ {1:1,3:1} │
└───────────────┴───────────┘numericIndexedVectorPointwiseSubtract
도입 버전: v25.7.0
numericIndexedVector와 다른 numericIndexedVector 또는 숫자 상수 간에 원소별 뺄셈을 수행합니다.
구문
numericIndexedVectorPointwiseSubtract(v1, v2)인수
v1—numericIndexedVectorv2— 숫자 상수 또는numericIndexedVector객체입니다.(U)Int*또는Float*또는numericIndexedVector
반환 값
새 numericIndexedVector 객체를 반환합니다. numericIndexedVector
예시
사용 예시
WITH
numericIndexedVectorBuild(mapFromArrays([1, 2, 3], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec1,
numericIndexedVectorBuild(mapFromArrays([2, 3, 4], arrayMap(x -> toInt32(x), [10, 20, 30]))) AS vec2
SELECT
numericIndexedVectorToMap(numericIndexedVectorPointwiseSubtract(vec1, vec2)) AS res1,
numericIndexedVectorToMap(numericIndexedVectorPointwiseSubtract(vec1, 2)) AS res2;┌─res1───────────────────┬─res2────────────┐
│ {1:10,2:10,3:10,4:-30} │ {1:8,2:18,3:28} │
└────────────────────────┴─────────────────┘numericIndexedVectorShortDebugString
도입 버전: v25.7.0
numericIndexedVector의 내부 정보를 JSON 포맷으로 반환합니다. 이 함수는 주로 디버깅 용도로 사용됩니다.
구문
numericIndexedVectorShortDebugString(v)인수
반환 값
디버그 정보가 포함된 JSON 문자열을 반환합니다. String
예시
사용 예시
SELECT numericIndexedVectorShortDebugString(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res FORMAT Vertical;Row 1:
──────
res: {"vector_type":"BSI","index_type":"char8_t","value_type":"char8_t","integer_bit_num":8,"fraction_bit_num":0,"zero_indexes_info":{"cardinality":0},"non_zero_indexes_info":{"total_cardinality":3,"all_value_sum":60,"number_of_bitmaps":8,"bitmap_info":{"cardinality":{"0":0,"1":2,"2":2,"3":2,"4":2,"5":0,"6":0,"7":0}}}}numericIndexedVectorToMap
도입 버전: v25.7.0
numericIndexedVector를 맵으로 변환합니다.
구문
numericIndexedVectorToMap(v)인수
반환 값
인덱스-값 쌍으로 이루어진 맵을 반환합니다. Map
예시
사용 예시
SELECT numericIndexedVectorToMap(numericIndexedVectorBuild(mapFromArrays([1, 2, 3], [10, 20, 30]))) AS res;┌─res──────────────┐
│ {1:10,2:20,3:30} │
└──────────────────┘