스케치 기반 근사 함수

스케치 기반 근사 함수

Spark의 SQL과 DataFrame API는 Apache DataSketches 라이브러리가 제공하는 스케치 기반 근사 함수 모음을 제공해요. 이 함수들은 제한된 메모리 사용과 정확도 보장으로 대규모 데이터셋에서 효율적인 확률적 계산을 가능하게 해줘요.

스케치(sketch)는 대규모 데이터셋을 요약하는 컴팩트한 데이터 구조로, 직렬화와 병합(merge)을 통해 분산 집계를 지원해요. 이 때문에 다음과 같은 사용 사례에 아주 적합해요(지금까지).

  • 근사 고유값 개수(HLL, Theta, Tuple 스케치)
  • 근사 분위수(quantile) 추정(KLL 스케치)
  • 근사 빈발 항목(Top-K 스케치)
  • 고유 개수에 대한 집합 연산(Theta와 Tuple 스케치)
  • 집계 요약을 동반한 고유 개수 계산(Tuple 스케치)

목차

HyperLogLog (HLL) 스케치 함수

HyperLogLog 스케치는 정확도와 메모리 사용량을 조정할 수 있는 근사 고유값 개수 기능을 제공해요. 매우 큰 데이터셋에서 고유 값을 세는 데 아주 적합해요.

자세한 내용은 Apache DataSketches HLL 문서를 참조하세요.

hll_sketch_agg

입력 값으로 HLL 스케치를 만들어요. 나중에 고유값 개수를 추정하는 데 사용할 수 있어요.

문법:

`hll_sketch_agg(expr [, lgConfigK])
인자 타입 설명
expr INT, BIGINT, STRING, 또는 BINARY 고유값 개수를 셀 표현식
lgConfigK INT (선택) K의 log-base-2. K는 버킷 수예요. 범위: 4-21. 기본: 12. 값이 높을수록 더 정확하지만 메모리를 더 많이 써요.

업데이트 가능한 이진 표현의 HLL 스케치를 담은 BINARY를 반환해요.

예시:

-- 기본 사용법: 스케치를 만들고 고유값 개수 추정
SELECT hll_sketch_estimate(hll_sketch_agg(col))
FROM VALUES (1), (1), (2), (2), (3) tab(col);
-- 결과: 3

-- 더 높은 정확도를 위한 사용자 지정 lgConfigK
SELECT hll_sketch_estimate(hll_sketch_agg(col, 16))
FROM VALUES (50), (60), (60), (60), (75), (100) tab(col);
-- 결과: 4

-- 문자열 값 사용
SELECT hll_sketch_estimate(hll_sketch_agg(col))
FROM VALUES ('abc'), ('def'), ('abc'), ('ghi'), ('abc') tab(col);
-- 결과: 3

참고:

  • 집계 중 NULL 값은 무시돼요.
  • 빈 문자열(STRING 타입)과 빈 바이트 배열(BINARY 타입)은 무시돼요.
  • 스케치는 저장해 두었다가 hll_union 또는 hll_union_agg로 다른 스케치와 병합할 수 있어요.

hll_union_agg

여러 HLL 스케치를 하나의 병합된 스케치로 집계해요.

문법:

`hll_union_agg(sketch [, allowDifferentLgConfigK])
인자 타입 설명
sketch BINARY 이진 형식의 HLL 스케치(hll_sketch_agg가 생성)
allowDifferentLgConfigK BOOLEAN (선택) true이면 다른 lgConfigK 값을 가진 스케치를 병합할 수 있어요. 기본: false.

병합된 HLL 스케치를 담은 BINARY를 반환해요.

예시:

-- 다른 파티션의 스케치 병합
SELECT hll_sketch_estimate(hll_union_agg(sketch, true))
FROM (
  SELECT hll_sketch_agg(col) as sketch
  FROM VALUES (1) tab(col)
  UNION ALL
  SELECT hll_sketch_agg(col, 20) as sketch
  FROM VALUES (1) tab(col)
);
-- 결과: 1

-- 표준 병합(같은 lgConfigK)
SELECT hll_sketch_estimate(hll_union_agg(sketch))
FROM (
  SELECT hll_sketch_agg(col) as sketch
  FROM VALUES (1), (2) tab(col)
  UNION ALL
  SELECT hll_sketch_agg(col) as sketch
  FROM VALUES (3), (4) tab(col)
);
-- 결과: 4

참고:

  • allowDifferentLgConfigK가 false이고 스케치들이 서로 다른 lgConfigK 값을 가지면 오류가 발생해요.
  • 서로 다른 크기의 스케치를 병합할 때 출력 스케치는 모든 입력 스케치의 lgConfigK 값 중 최솟값을 사용해요.

hll_sketch_estimate

HLL 스케치에서 고유 값의 개수를 추정해요.

문법:

`hll_sketch_estimate(sketch)
인자 타입 설명
sketch BINARY 이진 형식의 HLL 스케치

추정된 고유 값 개수를 나타내는 BIGINT를 반환해요.

예시:

SELECT hll_sketch_estimate(hll_sketch_agg(col))
FROM VALUES (1), (1), (2), (2), (3) tab(col);
-- 결과: 3

오류:

  • 입력이 유효한 HLL 스케치 이진 표현이 아니면 오류를 발생시켜요.

hll_union

두 HLL 스케치를 하나로 병합해요(스칼라 함수).

문법:

`hll_union(first, second [, allowDifferentLgConfigK])
인자 타입 설명
first BINARY 첫 번째 HLL 스케치
second BINARY 두 번째 HLL 스케치
allowDifferentLgConfigK BOOLEAN (선택) 다른 lgConfigK 값 허용. 기본: false.

병합된 HLL 스케치를 담은 BINARY를 반환해요.

예시:

SELECT hll_sketch_estimate(
  hll_union(
    hll_sketch_agg(col1),
    hll_sketch_agg(col2)))
FROM VALUES (1, 4), (1, 4), (2, 5), (2, 5), (3, 6) tab(col1, col2);
-- 결과: 6

Theta 스케치 함수

Theta 스케치는 집합 연산(합집합, 교집합, 차집합)을 지원하는 근사 고유값 개수를 제공해요. 이 때문에 겹치는 데이터셋에서 고유 개수를 계산하는 데 아주 적합해요.

참고: 고유 개수와 함께 집계 지표(연관된 값의 합, 최소, 최대 등)도 추적해야 한다면, Theta 스케치에 숫자 요약 값을 확장한 Tuple 스케치 함수를 대신 고려해 보세요.

자세한 내용은 Apache DataSketches Theta 문서를 참조하세요.

theta_sketch_agg

입력 값으로 Theta 스케치를 만들어요.

문법:

`theta_sketch_agg(expr [, lgNomEntries])
인자 타입 설명
expr INT, BIGINT, FLOAT, DOUBLE, STRING, BINARY, ARRAY, 또는 ARRAY 고유값 개수를 셀 표현식
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.

컴팩트 이진 표현의 Theta 스케치를 담은 BINARY를 반환해요.

예시:

-- 기본 고유 개수
SELECT theta_sketch_estimate(theta_sketch_agg(col))
FROM VALUES (1), (1), (2), (2), (3) tab(col);
-- 결과: 3

-- 사용자 지정 lgNomEntries
SELECT theta_sketch_estimate(theta_sketch_agg(col, 22))
FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col);
-- 결과: 7

-- 배열 값 사용
SELECT theta_sketch_estimate(theta_sketch_agg(col))
FROM VALUES (ARRAY(1, 2)), (ARRAY(3, 4)), (ARRAY(1, 2)) tab(col);
-- 결과: 2

참고:

  • NULL 값은 무시돼요.
  • HLL 스케치보다 더 넓은 범위의 입력 타입을 지원해요.
  • 빈 배열, 빈 문자열, 빈 이진 값은 무시돼요.

theta_union_agg

합집합 연산으로 여러 Theta 스케치를 집계해요.

문법:

`theta_union_agg(sketch [, lgNomEntries])
인자 타입 설명
sketch BINARY 이진 형식의 Theta 스케치
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.

병합된 Theta 스케치를 담은 BINARY를 반환해요.

예시:

SELECT theta_sketch_estimate(theta_union_agg(sketch, 15))
FROM (
  SELECT theta_sketch_agg(col1) as sketch
  FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col1)
  UNION ALL
  SELECT theta_sketch_agg(col2, 20) as sketch
  FROM VALUES (5), (6), (7), (8), (9), (10), (11) tab(col2)
);
-- 결과: 11

theta_intersection_agg

교집합 연산으로 여러 Theta 스케치를 집계해요(공통 고유 값을 찾음).

문법:

`theta_intersection_agg(sketch)
인자 타입 설명
sketch BINARY 이진 형식의 Theta 스케치

교집합된 Theta 스케치를 담은 BINARY를 반환해요.

예시:

SELECT theta_sketch_estimate(theta_intersection_agg(sketch))
FROM (
  SELECT theta_sketch_agg(col1) as sketch
  FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col1)
  UNION ALL
  SELECT theta_sketch_agg(col2) as sketch
  FROM VALUES (5), (6), (7), (8), (9), (10), (11) tab(col2)
);
-- 결과: 3 (5, 6, 7 값이 공통)

theta_sketch_estimate

Theta 스케치에서 고유 값의 개수를 추정해요.

문법:

`theta_sketch_estimate(sketch)
인자 타입 설명
sketch BINARY 이진 형식의 Theta 스케치

추정된 고유 값 개수를 나타내는 BIGINT를 반환해요.

예시:

SELECT theta_sketch_estimate(theta_sketch_agg(col))
FROM VALUES (1), (1), (2), (2), (3) tab(col);
-- 결과: 3

theta_union

합집합으로 두 Theta 스케치를 병합해요(스칼라 함수).

문법:

`theta_union(first, second [, lgNomEntries])
인자 타입 설명
first BINARY 첫 번째 Theta 스케치
second BINARY 두 번째 Theta 스케치
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.

병합된 Theta 스케치를 담은 BINARY를 반환해요.

예시:

SELECT theta_sketch_estimate(
  theta_union(
    theta_sketch_agg(col1),
    theta_sketch_agg(col2)))
FROM VALUES (1, 4), (1, 4), (2, 5), (2, 5), (3, 6) tab(col1, col2);
-- 결과: 6

theta_intersection

두 Theta 스케치의 교집합을 계산해요(스칼라 함수).

문법:

`theta_intersection(first, second)
인자 타입 설명
first BINARY 첫 번째 Theta 스케치
second BINARY 두 번째 Theta 스케치

교집합된 Theta 스케치를 담은 BINARY를 반환해요.

예시:

SELECT theta_sketch_estimate(
  theta_intersection(
    theta_sketch_agg(col1),
    theta_sketch_agg(col2)))
FROM VALUES (5, 4), (1, 4), (2, 5), (2, 5), (3, 1) tab(col1, col2);
-- 결과: 2 (1과 5 값이 공통)

theta_difference

두 Theta 스케치의 차집합(A - B)을 계산해요.

문법:

`theta_difference(first, second)
인자 타입 설명
first BINARY 첫 번째 Theta 스케치 (A)
second BINARY 두 번째 Theta 스케치 (B)

A에는 있지만 B에는 없는 값을 나타내는 Theta 스케치를 담은 BINARY를 반환해요.

예시:

SELECT theta_sketch_estimate(
  theta_difference(
    theta_sketch_agg(col1),
    theta_sketch_agg(col2)))
FROM VALUES (5, 4), (1, 4), (2, 5), (2, 5), (3, 1) tab(col1, col2);
-- 결과: 2 (2와 3 값은 col1에 있지만 col2에 없음)

Tuple 스케치 함수

Tuple 스케치는 각 고유 키에 숫자 요약 값을 연결해 Theta 스케치를 확장해요. 집합 연산(합집합, 교집합, 차집합)과 함께 근사 고유 개수를 제공하면서, 구성 가능한 모드(sum, min, max 등)로 요약 값도 집계해요. 이 때문에 카디널리티 추정과 집계 지표를 둘 다 필요로 하는 시나리오에 유용해요.

참고: 집계 지표 없이 고유 개수만 필요하다면, 순수 카디널리티 추정에 더 메모리 효율적인 Theta 스케치 함수를 대신 고려해 보세요.

자세한 내용은 Apache DataSketches Tuple 문서를 참조하세요.

Tuple 함수는 타입에 따라 다릅니다.

  • DOUBLE 변형: 배정밀도 부동 소수점 요약 값용
  • INTEGER 변형: 정수 요약 값용

요약 집계 모드: 같은 키에 여러 값이 연결될 때(스케치 생성 또는 집합 연산 중), 모드 매개변수가 요약 값을 어떻게 결합할지 결정해요.

  • sum: 모든 요약 값을 더해요(기본)
  • min: 최소 요약 값을 유지해요
  • max: 최대 요약 값을 유지해요
  • alwaysone: 모든 요약 값을 1로 설정해요. 스케치를 Theta 스케치처럼 효과적으로 취급해요(Tuple 스케치를 카디널리티 전용 분석으로 변환하는 데 유용).

tuple_sketch_agg_*

키-값 쌍에서 Tuple 스케치를 만들고, distinct 키에 대한 요약 값을 집계해요.

문법:

`tuple_sketch_agg_double(key, summary [, lgNomEntries] [, mode])
tuple_sketch_agg_integer(key, summary [, lgNomEntries] [, mode])
인자 타입 설명
key INT, BIGINT, FLOAT, DOUBLE, STRING, BINARY, ARRAY, 또는 ARRAY 고유 개수를 셀 키 컬럼
summary DOUBLE(_double용) 또는 INT(_integer용) 각 키에 대해 집계할 숫자 값
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"(모든 요약 값을 1로 설정)

컴팩트 이진 표현의 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 기본 사용법: distinct 키를 세고 그 값들을 합산
SELECT
  tuple_sketch_estimate_integer(tuple_sketch_agg_integer(key, value)) as distinct_keys,
  tuple_sketch_summary_integer(tuple_sketch_agg_integer(key, value)) as total_value
FROM VALUES (1, 10), (2, 20), (2, 30) tab(key, value);
-- 결과: distinct_keys=2, total_value=60

-- 사용자 지정 lgNomEntries와 mode
SELECT tuple_sketch_summary_double(
  tuple_sketch_agg_double(key, value, 16, 'sum'), 'max')
FROM VALUES (1, 10.0), (2, 20.0), (2, 30.0) tab(key, value);
-- 결과: 50.0 (distinct 키의 최대 값)

참고:

  • 집계 중 NULL 키는 무시돼요.
  • 같은 키가 여러 번 나타나면 mode 매개변수에 따라 요약 값이 집계돼요.
  • 스케치는 저장해 두었다가 tuple 합집합/교집합 함수로 병합할 수 있어요.

tuple_union_agg_*

합집합 연산으로 여러 Tuple 스케치를 집계해요. 모든 스케치의 distinct 키를 결합해요.

문법:

`tuple_union_agg_double(sketch [, lgNomEntries] [, mode])
tuple_union_agg_integer(sketch [, lgNomEntries] [, mode])
인자 타입 설명
sketch BINARY 이진 형식의 Tuple 스케치
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"(모든 요약 값을 1로 설정)

병합된 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 다른 데이터 소스의 스케치 병합
SELECT tuple_sketch_estimate_double(tuple_union_agg_double(sketch))
FROM (
  SELECT tuple_sketch_agg_double(key, value) as sketch
  FROM VALUES (1, 10.0), (2, 20.0) tab(key, value)
  UNION ALL
  SELECT tuple_sketch_agg_double(key, value) as sketch
  FROM VALUES (3, 30.0), (4, 40.0) tab(key, value)
);
-- 결과: 4.0 (키 1,2,3,4의 합집합)

tuple_intersection_agg_*

교집합 연산으로 여러 Tuple 스케치를 집계해요. 공통 distinct 키를 찾아요.

문법:

`tuple_intersection_agg_double(sketch [, mode])
tuple_intersection_agg_integer(sketch [, mode])
인자 타입 설명
sketch BINARY 이진 형식의 Tuple 스케치
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"(모든 요약 값을 1로 설정)

교집합된 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 스케치들 사이의 공통 키 찾기
SELECT tuple_sketch_estimate_integer(tuple_intersection_agg_integer(sketch))
FROM (
  SELECT tuple_sketch_agg_integer(key, value) as sketch
  FROM VALUES (1, 10), (2, 20), (3, 30) tab(key, value)
  UNION ALL
  SELECT tuple_sketch_agg_integer(key, value) as sketch
  FROM VALUES (2, 40), (3, 50), (4, 60) tab(key, value)
);
-- 결과: 2.0 (키 2와 3이 공통)

tuple_sketch_estimate_*

Tuple 스케치에서 distinct 키의 개수를 추정해요.

문법:

`tuple_sketch_estimate_double(sketch)
tuple_sketch_estimate_integer(sketch)
인자 타입 설명
sketch BINARY 이진 형식의 Tuple 스케치

추정된 distinct 키 개수를 나타내는 DOUBLE을 반환해요.

예시:

SELECT tuple_sketch_estimate_double(
  tuple_sketch_agg_double(key, value))
FROM VALUES (1, 10.0), (2, 20.0), (2, 30.0) tab(key, value);
-- 결과: 2.0

tuple_sketch_summary_*

Tuple 스케치에서 집계된 요약 값을 반환해요.

문법:

`tuple_sketch_summary_double(sketch [, mode])
tuple_sketch_summary_integer(sketch [, mode])
인자 타입 설명
sketch BINARY 이진 형식의 Tuple 스케치
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"(모든 요약 값을 1로 설정)

집계된 요약 값(변형에 따라 DOUBLE 또는 BIGINT)을 반환해요.

예시:

-- 모든 요약 값의 합 구하기
SELECT tuple_sketch_summary_integer(
  tuple_sketch_agg_integer(key, value))
FROM VALUES (1, 10), (2, 20), (2, 30) tab(key, value);
-- 결과: 60 (10 + 20 + 30, 키 2의 값은 합산됨)

tuple_sketch_theta_*

Tuple 스케치에서 theta 값을 반환해요. 샘플링 비율을 나타내요.

문법:

`tuple_sketch_theta_double(sketch)
tuple_sketch_theta_integer(sketch)
인자 타입 설명
sketch BINARY 이진 형식의 Tuple 스케치

theta 값을 나타내는 0.0과 1.0 사이의 DOUBLE을 반환해요(1.0은 샘플링 없음을 의미).

예시:

SELECT tuple_sketch_theta_double(
  tuple_sketch_agg_double(key, value))
FROM VALUES (1, 10.0), (2, 20.0) tab(key, value);
-- 결과: 1.0

tuple_union_*

합집합으로 두 Tuple 스케치를 병합해요(스칼라 함수).

문법:

`tuple_union_double(first, second [, lgNomEntries] [, mode])
tuple_union_integer(first, second [, lgNomEntries] [, mode])
인자 타입 설명
first BINARY 첫 번째 Tuple 스케치
second BINARY 두 번째 Tuple 스케치
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"(모든 요약 값을 1로 설정)

병합된 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 다른 컬럼의 두 스케치 합집합
SELECT tuple_sketch_estimate_double(
  tuple_union_double(
    tuple_sketch_agg_double(key1, v1),
    tuple_sketch_agg_double(key2, v2)))
FROM VALUES (1, 10.0, 3, 30.0), (2, 20.0, 4, 40.0) tab(key1, v1, key2, v2);
-- 결과: 4.0 (키 1,2,3,4가 합집합에 있음)

tuple_intersection_*

두 Tuple 스케치의 교집합을 계산해요(스칼라 함수).

문법:

`tuple_intersection_double(first, second [, mode])
tuple_intersection_integer(first, second [, mode])
인자 타입 설명
first BINARY 첫 번째 Tuple 스케치
second BINARY 두 번째 Tuple 스케치
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"(모든 요약 값을 1로 설정)

교집합된 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 두 스케치 모두에 존재하는 키 찾기
SELECT tuple_sketch_estimate_integer(
  tuple_intersection_integer(
    tuple_sketch_agg_integer(key1, v1),
    tuple_sketch_agg_integer(key2, v2)))
FROM VALUES (1, 10, 2, 20), (2, 20, 3, 30), (3, 30, 4, 40) tab(key1, v1, key2, v2);
-- 결과: 2.0 (키 2와 3이 공통)

tuple_difference_*

두 Tuple 스케치의 차집합(A - B)을 계산해요. 첫 번째 스케치에는 있지만 두 번째에는 없는 키를 반환해요.

문법:

`tuple_difference_double(first, second)
tuple_difference_integer(first, second)
인자 타입 설명
first BINARY 첫 번째 Tuple 스케치 (A)
second BINARY 두 번째 Tuple 스케치 (B)

A에는 있지만 B에는 없는 키를 나타내는 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 첫 번째 스케치에만 있는 키 찾기
SELECT tuple_sketch_estimate_double(
  tuple_difference_double(
    tuple_sketch_agg_double(key1, v1),
    tuple_sketch_agg_double(key2, v2)))
FROM VALUES (1, 10.0, 4, 40.0), (2, 20.0, 4, 40.0), (3, 30.0, 5, 50.0), (4, 40.0, 5, 50.0) tab(key1, v1, key2, v2);
-- 결과: 3.0 (키 1, 2, 3은 key1에 있지만 key2에 없음)

tuple_union_theta_*

합집합으로 Tuple 스케치와 Theta 스케치를 병합해요(스칼라 함수). 두 스케치의 distinct 키를 결합하며, Theta 스케치 항목에는 기본 요약 값이 할당돼요.

문법:

`tuple_union_theta_double(tupleSketch, thetaSketch [, lgNomEntries] [, mode])
tuple_union_theta_integer(tupleSketch, thetaSketch [, lgNomEntries] [, mode])
인자 타입 설명
tupleSketch BINARY double/integer 요약을 가진 Tuple 스케치
thetaSketch BINARY Theta 스케치(키만)
lgNomEntries INT (선택) nominal entries의 log-base-2. 범위: 4-26. 기본: 12.
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"

병합된 Tuple 스케치를 담은 BINARY를 반환해요.

참고:

  • Theta 스케치 항목(요약 값이 없는 키)을 Tuple 스케치 항목과 병합할 때, mode에 기반한 기본 요약 값을 받아요.

  • sum 모드: 0.0 (덧셈의 항등원)

  • min 모드: +Infinity (최솟값의 항등원)

  • max 모드: -Infinity (최댓값의 항등원)

  • alwaysone 모드: 1.0 (모든 항목이 1로 설정)

예시:

-- Tuple 스케치와 Theta 스케치 합집합
SELECT tuple_sketch_estimate_double(
  tuple_union_theta_double(
    tuple_sketch_agg_double(user_id, spend),
    theta_sketch_agg(visitor_id)))
FROM VALUES (1, 10.0), (2, 20.0) users(user_id, spend)
CROSS JOIN (VALUES (3), (4) visitors(visitor_id));
-- 결과: 4.0 (모든 키: 1, 2, 3, 4)

-- 사용자 지정 lgNomEntries와 mode
SELECT tuple_sketch_estimate_integer(
  tuple_union_theta_integer(
    tuple_sketch_agg_integer(user_id, count),
    theta_sketch_agg(visitor_id),
    16,
    'sum'))
FROM VALUES (1, 5), (2, 10) users(user_id, count)
CROSS JOIN (VALUES (3), (4) visitors(visitor_id));
-- 결과: 4.0

사용 사례: 사용자 활동 데이터(Tuple 스케치)와 익명 방문자 데이터(Theta 스케치)를 결합해 두 그룹 전체의 총 고유 사용자를 구하는 데 유용해요.

tuple_intersection_theta_*

Tuple 스케치와 Theta 스케치의 교집합을 계산해요(스칼라 함수). 두 스케치 모두에 존재하는 키를 반환하며, Tuple 스케치의 요약 값을 보존해요.

문법:

`tuple_intersection_theta_double(tupleSketch, thetaSketch [, mode])
tuple_intersection_theta_integer(tupleSketch, thetaSketch [, mode])
인자 타입 설명
tupleSketch BINARY double/integer 요약을 가진 Tuple 스케치
thetaSketch BINARY Theta 스케치(키만)
mode STRING (선택) 요약 집계 모드: "sum"(기본), "min", "max", "alwaysone"

교집합된 Tuple 스케치를 담은 BINARY를 반환해요.

참고:

  • Theta 스케치 항목(요약 값이 없는 키)을 Tuple 스케치 항목과 교집합할 때, mode에 기반한 기본 요약 값을 받아요.

  • sum 모드: 0.0 (덧셈의 항등원)

  • min 모드: +Infinity (최솟값의 항등원)

  • max 모드: -Infinity (최댓값의 항등원)

  • alwaysone 모드: 1.0 (모든 항목이 1로 설정)

예시:

-- 방문자로도 나타나는 등록 사용자 찾기
SELECT tuple_sketch_estimate_double(
  tuple_intersection_theta_double(
    tuple_sketch_agg_double(user_id, spend),
    theta_sketch_agg(visitor_id)))
FROM VALUES (1, 10.0), (2, 20.0), (3, 30.0) users(user_id, spend)
CROSS JOIN (VALUES (2), (3), (4) visitors(visitor_id));
-- 결과: 2.0 (키 2와 3이 공통)

-- mode 매개변수 사용
SELECT tuple_sketch_summary_integer(
  tuple_intersection_theta_integer(
    tuple_sketch_agg_integer(user_id, count),
    theta_sketch_agg(visitor_id),
    'sum'))
FROM VALUES (1, 5), (2, 10), (3, 15) users(user_id, count)
CROSS JOIN (VALUES (2), (3), (4) visitors(visitor_id));
-- 결과: 25 (키 2와 3의 count 합)

사용 사례: 방문자 로그에도 나타나는 등록 사용자를 식별하고, 그들의 연관 지표(k)를 집계하는 데 유용해요.

tuple_difference_theta_*

Tuple 스케치와 Theta 스케치 사이의 차집합(A - B)을 계산해요. Theta 스케치에 없는 Tuple 스케치 키를 반환하며 요약 값을 보존해요.

문법:

`tuple_difference_theta_double(tupleSketch, thetaSketch)
tuple_difference_theta_integer(tupleSketch, thetaSketch)
인자 타입 설명
tupleSketch BINARY double/integer 요약을 가진 Tuple 스케치 (A)
thetaSketch BINARY Theta 스케치 (B)

A에는 있지만 B에는 없는 키를 나타내는 Tuple 스케치를 담은 BINARY를 반환해요.

예시:

-- 최근에 방문하지 않은 등록 사용자 찾기
SELECT tuple_sketch_estimate_double(
  tuple_difference_theta_double(
    tuple_sketch_agg_double(user_id, lifetime_spend),
    theta_sketch_agg(recent_visitor_id)))
FROM VALUES (1, 100.0), (2, 200.0), (3, 300.0), (5, 500.0) all_users(user_id, lifetime_spend)
CROSS JOIN (VALUES (1), (2), (4) recent_visitors(recent_visitor_id));
-- 결과: 2.0 (사용자 3과 5가 최근에 방문하지 않음)

-- 최근에 방문하지 않은 사용자의 총 평생 지출 구하기
SELECT tuple_sketch_summary_double(
  tuple_difference_theta_double(
    tuple_sketch_agg_double(user_id, lifetime_spend),
    theta_sketch_agg(recent_visitor_id)))
FROM VALUES (1, 100.0), (2, 200.0), (3, 300.0), (5, 500.0) all_users(user_id, lifetime_spend)
CROSS JOIN (VALUES (1), (2), (4) recent_visitors(recent_visitor_id));
-- 결과: 800.0 (사용자 3과 5의 300.0 + 500.0 합)

사용 사례: 비활성 사용자(최근에 방문하지 않은 등록 사용자)를 식별하고 총 평생 가치 같은 집계 지표를 계산해 재참여 캠페인 우선순위를 정하는 데 유용해요.

KLL 분위수 스케치 함수

KLL (Karnin-Lang-Liberty) 스케치는 근사 분위수 추정을 제공해요. 정렬 없이 대규모 데이터셋에서 백분위수, 중앙값, 기타 순서 통계를 계산하는 데 유용해요.

자세한 내용은 Apache DataSketches KLL 문서를 참조하세요.

KLL 함수는 정밀도 손실을 피하기 위해 타입에 따라 다릅니다.

  • BIGINT 변형: 정수 타입(TINYINT, SMALLINT, INT, BIGINT)용
  • FLOAT 변형: FLOAT 값 전용
  • DOUBLE 변형: FLOAT와 DOUBLE 값용

kll_sketch_agg_*

분위수 추정을 위해 숫자 값으로 KLL 스케치를 만들어요.

문법:

`kll_sketch_agg_bigint(expr [, k])
kll_sketch_agg_float(expr [, k])
kll_sketch_agg_double(expr [, k])
인자 타입 설명
expr 숫자(위 변형 참조) 요약할 숫자 컬럼
k INT (선택) 정확도와 크기를 제어해요. 범위: 8-65535. 기본: 200 (~1.65% 정규화 rank 오차).

컴팩트 이진 표현의 KLL 스케치를 담은 BINARY를 반환해요.

예시:

-- 중앙값(0.5 분위수) 구하기
SELECT kll_sketch_get_quantile_bigint(kll_sketch_agg_bigint(col), 0.5)
FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col);
-- 결과: 4

-- 더 높은 정확도를 위한 사용자 지정 k
SELECT kll_sketch_get_quantile_bigint(kll_sketch_agg_bigint(col, 400), 0.5)
FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col);
-- 결과: 4

참고:

  • 정밀도 손실을 피하려면 적절한 변형을 사용하세요: 정수에는 _bigint, float에는 _float, double에는 _double.
  • 집계 중 NULL 값은 무시돼요.

kll_merge_agg_*

같은 타입의 여러 KLL 스케치를 병합해 집계해요. 별도의 집계에서 만든 스케치(예: 다른 파티션이나 시간 창)를 결합하는 데 유용해요. 이들은 집계 함수예요.

문법:

`kll_merge_agg_bigint(sketch [, k])
kll_merge_agg_float(sketch [, k])
kll_merge_agg_double(sketch [, k])
인자 타입 설명
sketch BINARY 이진 형식의 KLL 스케치(예: kll_sketch_agg_*에서)
k INT (선택) 병합된 스케치의 정확도와 크기를 제어해요. 범위: 8-65535. 지정하지 않으면 병합된 스케치는 첫 번째 입력 스케치의 k 값을 채택해요.

병합된 KLL 스케치를 담은 BINARY를 반환해요.

예시:

-- 다른 파티션의 스케치 병합
SELECT kll_sketch_get_quantile_bigint(
  kll_merge_agg_bigint(sketch),
  0.5
)
FROM (
  SELECT kll_sketch_agg_bigint(col) as sketch
  FROM VALUES (1), (2), (3) tab(col)
  UNION ALL
  SELECT kll_sketch_agg_bigint(col) as sketch
  FROM VALUES (4), (5), (6) tab(col)
);
-- 결과: 3

-- 병합된 스케치에서 총 개수 구하기
SELECT kll_sketch_get_n_bigint(kll_merge_agg_bigint(sketch))
FROM (
  SELECT kll_sketch_agg_bigint(col) as sketch
  FROM VALUES (1), (2), (3) tab(col)
  UNION ALL
  SELECT kll_sketch_agg_bigint(col) as sketch
  FROM VALUES (4), (5), (6) tab(col)
);
-- 결과: 6

참고:

  • k를 지정하지 않으면 병합된 스케치는 첫 번째 입력 스케치의 k 값을 채택해요.
  • 병합 연산은 서로 다른 k 값을 가진 입력 스케치를 처리할 수 있어요.
  • 집계 중 NULL 값은 무시돼요.
  • 집계 맥락에서 여러 스케치를 병합해야 할 때 이 함수를 사용하세요. 정확히 두 스케치를 병합할 때는 스칼라 kll_sketch_merge_* 함수를 대신 사용하세요.

kll_sketch_to_string_*

스케치의 사람이 읽을 수 있는 요약을 반환해요.

문법:

`kll_sketch_to_string_bigint(sketch)
kll_sketch_to_string_float(sketch)
kll_sketch_to_string_double(sketch)
인자 타입 설명
sketch BINARY 해당 타입의 KLL 스케치

스케치 매개변수와 통계를 포함한 사람이 읽을 수 있는 요약을 담은 STRING을 반환해요.

kll_sketch_get_n_*

스케치에 수집된 항목의 개수를 반환해요.

문법:

`kll_sketch_get_n_bigint(sketch)
kll_sketch_get_n_float(sketch)
kll_sketch_get_n_double(sketch)
인자 타입 설명
sketch BINARY 해당 타입의 KLL 스케치

스케치의 항목 개수를 나타내는 BIGINT를 반환해요.

예시:

SELECT kll_sketch_get_n_bigint(kll_sketch_agg_bigint(col))
FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col);
-- 결과: 7

kll_sketch_merge_*

같은 타입의 두 KLL 스케치를 병합해요. 이들은 스칼라 함수예요.

문법:

`kll_sketch_merge_bigint(left, right)
kll_sketch_merge_float(left, right)
kll_sketch_merge_double(left, right)
인자 타입 설명
left BINARY 첫 번째 KLL 스케치
right BINARY 두 번째 KLL 스케치(left와 같은 타입이어야 함)

병합된 KLL 스케치를 담은 BINARY를 반환해요.

예시:

-- 다른 데이터 파티션의 두 스케치 병합
SELECT kll_sketch_get_quantile_bigint(
  kll_sketch_merge_bigint(
    kll_sketch_agg_bigint(col1),
    kll_sketch_agg_bigint(col2)), 0.5)
FROM VALUES (1, 6), (2, 7), (3, 8), (4, 9), (5, 10) tab(col1, col2);
-- 결과: 약 5 (1-10의 중앙값)

오류:

  • 스케치가 호환되지 않는 타입이나 형식이면 오류를 발생시켜요.

참고:

  • 병합 연산은 서로 다른 k 값을 가진 입력 스케치를 처리할 수 있어요.
  • 스칼라 맥락에서 정확히 두 스케치를 병합해야 할 때 이 함수를 사용하세요. 집계 맥락에서 여러 스케치를 병합할 때는 집계 kll_merge_agg_* 함수를 대신 사용하세요.

kll_sketch_get_quantile_*

주어진 분위수 rank에서 근사 값을 얻어요.

문법:

`kll_sketch_get_quantile_bigint(sketch, rank)
kll_sketch_get_quantile_float(sketch, rank)
kll_sketch_get_quantile_double(sketch, rank)
인자 타입 설명
sketch BINARY 해당 타입의 KLL 스케치
rank DOUBLE 또는 ARRAY 0.0과 1.0 사이의 분위수 rank(들). 중앙값에는 0.5, 95번째 백분위수에는 0.95 등을 사용해요.

주어진 분위수의 근사 값을 반환해요.

  • rank가 스칼라이면: 해당 타입(BIGINT, FLOAT, 또는 DOUBLE) 반환
  • rank가 배열이면: 해당 타입의 ARRAY 반환

예시:

-- 중앙값 구하기
SELECT kll_sketch_get_quantile_bigint(kll_sketch_agg_bigint(col), 0.5)
FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col);
-- 결과: 4

-- 여러 백분위수를 한 번에 구하기
SELECT kll_sketch_get_quantile_bigint(
  kll_sketch_agg_bigint(col),
  ARRAY(0.25, 0.5, 0.75, 0.95))
FROM VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10) tab(col);
-- 결과: 25번째, 50번째, 75번째, 95번째 백분위수의 값 배열

오류:

  • rank 값이 [0.0, 1.0] 범위를 벗어나면 오류를 발생시켜요.
  • 입력 스케치가 NULL이면 NULL을 반환해요.

kll_sketch_get_rank_*

스케치 분포에서 주어진 값의 정규화된 rank(0.0에서 1.0)를 얻어요.

문법:

`kll_sketch_get_rank_bigint(sketch, value)
kll_sketch_get_rank_float(sketch, value)
kll_sketch_get_rank_double(sketch, value)
인자 타입 설명
sketch BINARY 해당 타입의 KLL 스케치
value 해당 타입(BIGINT, FLOAT, 또는 DOUBLE) rank를 찾을 값

0.0과 1.0 사이의 정규화된 rank를 나타내는 DOUBLE을 반환해요.

예시:

-- 값 3이 어느 백분위수에 있는지 찾기
SELECT kll_sketch_get_rank_bigint(kll_sketch_agg_bigint(col), 3)
FROM VALUES (1), (2), (3), (4), (5), (6), (7) tab(col);
-- 결과: 약 0.43 (3은 대략 43번째 백분위수)

근사 Top-K 함수

Top-K 함수는 DataSketches 빈발 항목(Frequent Items) 스케치를 사용해 데이터셋에서 가장 빈번한 항목(heavy hitters)을 추정해요.

자세한 내용은 Apache DataSketches Frequency 문서를 참조하세요.

approx_top_k_accumulate

저장했다가 나중에 결합하거나 추정할 수 있는 스케치를 만들어요. 데이터를 사전 집계하는 데 유용해요.

문법:

`approx_top_k_accumulate(expr [, maxItemsTracked])
인자 타입 설명
expr approx_top_k와 동일 누적할 컬럼
maxItemsTracked INT (선택) 추적되는 최대 항목 수. 범위: 1 ~ 1,000,000. 기본: 10,000.

approx_top_k_combine 또는 approx_top_k_estimate에 전달할 수 있는 스케치 상태를 담은 STRUCT를 반환해요.

예시:

-- 누적 후 추정
SELECT approx_top_k_estimate(approx_top_k_accumulate(expr))
FROM VALUES (0), (0), (1), (1), (2), (3), (4), (4) tab(expr);
-- 결과: [{"item":0,"count":2},{"item":4,"count":2},{"item":1,"count":2},{"item":2,"count":1},{"item":3,"count":1}]

approx_top_k_combine

여러 스케치를 하나의 스케치로 결합해요.

문법:

`approx_top_k_combine(state [, maxItemsTracked])
인자 타입 설명
state STRUCT approx_top_k_accumulate 또는 approx_top_k_combine의 스케치 상태
maxItemsTracked INT (선택) 지정하면 결합된 스케치 크기를 설정해요. 지정하지 않으면 모든 입력 스케치가 같은 maxItemsTracked를 가져야 해요.

결합된 스케치 상태를 담은 STRUCT를 반환해요.

예시:

-- 다른 파티션의 스케치 결합
SELECT approx_top_k_estimate(approx_top_k_combine(sketch, 10000), 5)
FROM (
  SELECT approx_top_k_accumulate(expr) AS sketch
  FROM VALUES (0), (0), (1), (1) tab(expr)
  UNION ALL
  SELECT approx_top_k_accumulate(expr) AS sketch
  FROM VALUES (2), (3), (4), (4) tab(expr)
);
-- 결과: [{"item":0,"count":2},{"item":4,"count":2},{"item":1,"count":2},{"item":2,"count":1},{"item":3,"count":1}]

오류:

  • 입력 스케치들이 서로 다른 maxItemsTracked 값을 가지고 명시적 값도 제공되지 않으면 오류를 발생시켜요.
  • 입력 스케치들이 서로 다른 항목 데이터 타입을 가지면 오류를 발생시켜요.

approx_top_k_estimate

스케치에서 상위 K 항목을 추출해요.

문법:

`approx_top_k_estimate(state [, k])
인자 타입 설명
state STRUCT approx_top_k_accumulate 또는 approx_top_k_combine의 스케치 상태
k INT (선택) 반환할 상위 항목 수. 기본: 5.

count 내림차순으로 정렬된 빈발 항목을 담은 ARRAY<STRUCT<item, count>>를 반환해요.

예시:

SELECT approx_top_k_estimate(approx_top_k_accumulate(expr), 2)
FROM VALUES 'a', 'b', 'c', 'c', 'c', 'c', 'd', 'd' tab(expr);
-- 결과: [{"item":"c","count":4},{"item":"d","count":2}]

모범 사례

HLL, Theta, Tuple 스케치 중 선택하기

사용 사례 권장 스케치
단순 고유값 개수 HLL (가장 메모리 효율적)
집합 연산(합집합, 교집합, 차집합) Theta 또는 Tuple
집계 지표와 함께하는 고유 개수(sum, min, max) Tuple
보통 정확도로 매우 높은 카디널리티 더 높은 lgConfigK의 HLL
데이터셋 사이의 겹침 계산 필요 Theta 또는 Tuple
총 지출과 함께 고유 사용자 세기 Tuple (key=user_id, summary=spend)

정확도 대 메모리 절충

스케치 타입 매개변수 증가의 효과
HLL lgConfigK 더 높은 정확도, 더 많은 메모리(2^lgConfigK 바이트)
Theta lgNomEntries 더 높은 정확도, 더 많은 메모리(8 * 2^lgNomEntries 바이트)
Tuple lgNomEntries 더 높은 정확도, 더 많은 메모리(double은 16 * 2^lgNomEntries 바이트, integer는 12 * 2^lgNomEntries 바이트)
KLL k 더 높은 정확도, 더 많은 메모리
Top-K maxItemsTracked 더 나은 heavy-hitter 탐지, 더 많은 메모리

스케치 저장 및 재사용

스케치는 BINARY 컬럼에 저장하고 나중에 병합할 수 있어요.

-- 일일 스케치를 저장할 테이블 만들기
CREATE TABLE daily_user_sketches (
  date DATE,
  user_sketch BINARY
);

-- 일일 스케치 삽입
INSERT INTO daily_user_sketches
SELECT current_date(), hll_sketch_agg(user_id)
FROM events;

-- 일일 스케치를 병합해 주간 고유 사용자 계산
SELECT hll_sketch_estimate(hll_union_agg(user_sketch))
FROM daily_user_sketches
WHERE date BETWEEN '2024-01-01' AND '2024-01-07';

일반적인 사용 사례와 예시

스케치는 여러 배치의 데이터에 걸쳐 실행 중인 통계를 유지해야 하는 주기적 ETL 작업에 특히 가치가 있어요. 일반적인 워크플로는:

    • 집계 함수로 입력 값을 스케치로 집계하기
    • 스케치를(BINARY로) 테이블에 저장하기
    • 새 스케치를 기존에 저장된 스케치와 병합하기
    • 최종 스케치를 조회해 근사 답 얻기

예시: HLL 스케치로 일일 고유 사용자 추적

이 예시는 일일 배치에 걸쳐 고유 사용자의 실행 중인 개수를 유지하는 방법을 보여줘요.

-- 일일 HLL 스케치를 저장할 테이블 만들기
CREATE TABLE daily_user_sketches (
  event_date DATE,
  user_sketch BINARY
) USING PARQUET;

-- 1일차: 첫 번째 이벤트 배치를 처리하고 스케치 저장
INSERT INTO daily_user_sketches
SELECT 
  DATE'2024-01-01' as event_date,
  hll_sketch_agg(user_id) as user_sketch
FROM day1_events;

-- 2일차: 두 번째 배치를 처리하고 스케치 저장
INSERT INTO daily_user_sketches
SELECT 
  DATE'2024-01-02' as event_date,
  hll_sketch_agg(user_id) as user_sketch
FROM day2_events;

-- 조회: 하루의 고유 사용자 구하기
SELECT 
  event_date,
  hll_sketch_estimate(user_sketch) as unique_users
FROM daily_user_sketches
WHERE event_date = DATE'2024-01-01';

-- 조회: 날짜 범위에 걸친 고유 사용자 구하기(스케치 병합)
SELECT hll_sketch_estimate(hll_union_agg(user_sketch)) as unique_users_in_week
FROM daily_user_sketches
WHERE event_date BETWEEN DATE'2024-01-01' AND DATE'2024-01-07';

예시: KLL 스케치로 시간에 따른 백분위수 계산

이 예시는 시간별 배치에 걸쳐 응답 시간 백분위수를 추적하는 방법을 보여줘요.

-- 응답 시간의 시간별 KLL 스케치를 저장할 테이블 만들기
CREATE TABLE hourly_latency_sketches (
  hour_ts TIMESTAMP,
  latency_sketch BINARY
) USING PARQUET;

-- 각 시간의 데이터를 처리하고 스케치 저장
INSERT INTO hourly_latency_sketches
SELECT 
  DATE_TRUNC('hour', event_time) as hour_ts,
  kll_sketch_agg_bigint(response_time_ms) as latency_sketch
FROM hourly_events
GROUP BY DATE_TRUNC('hour', event_time);

-- 조회: 특정 시간의 p50, p95, p99 구하기
SELECT 
  hour_ts,
  kll_sketch_get_quantile_bigint(latency_sketch, 0.5) as p50_ms,
  kll_sketch_get_quantile_bigint(latency_sketch, 0.95) as p95_ms,
  kll_sketch_get_quantile_bigint(latency_sketch, 0.99) as p99_ms
FROM hourly_latency_sketches
WHERE hour_ts = TIMESTAMP'2024-01-15 14:00:00';

-- 조회: 시간별 스케치를 병합해 하루 전체의 백분위수 구하기
WITH daily_sketch AS (
  SELECT kll_merge_agg_bigint(latency_sketch) as merged_sketch
  FROM hourly_latency_sketches
  WHERE DATE(hour_ts) = DATE'2024-01-15'
)
SELECT
  kll_sketch_get_quantile_bigint(merged_sketch, 0.5) as p50_ms,
  kll_sketch_get_quantile_bigint(merged_sketch, 0.95) as p95_ms,
  kll_sketch_get_quantile_bigint(merged_sketch, 0.99) as p99_ms
FROM daily_sketch;

예시: Theta 스케치로 집합 연산

Theta 스케치는 집합 연산을 지원하므로 겹치는 모집단을 분석하는 데 유용해요.

-- 서로 다른 행동을 한 사용자의 스케치 만들기
CREATE TABLE action_sketches (
  action_type STRING,
  user_sketch BINARY
) USING PARQUET;

-- 각 행동 유형의 스케치 저장
INSERT INTO action_sketches
SELECT 'purchase', theta_sketch_agg(user_id) FROM purchases;

INSERT INTO action_sketches
SELECT 'add_to_cart', theta_sketch_agg(user_id) FROM cart_additions;

INSERT INTO action_sketches
SELECT 'page_view', theta_sketch_agg(user_id) FROM page_views;

-- 조회: 구매한 사용자는 몇 명인가요?
SELECT theta_sketch_estimate(user_sketch) as purchasers
FROM action_sketches WHERE action_type = 'purchase';

-- 조회: 장바구니에 담았지만 구매하지 않은 사용자는 몇 명인가요?
SELECT theta_sketch_estimate(
  theta_difference(
    (SELECT user_sketch FROM action_sketches WHERE action_type = 'add_to_cart'),
    (SELECT user_sketch FROM action_sketches WHERE action_type = 'purchase')
  )
) as cart_abandoners;

-- 조회: 페이지를 보고 동시에 구매한 사용자는 몇 명인가요(교집합)?
SELECT theta_sketch_estimate(
  theta_intersection(
    (SELECT user_sketch FROM action_sketches WHERE action_type = 'page_view'),
    (SELECT user_sketch FROM action_sketches WHERE action_type = 'purchase')
  )
) as engaged_purchasers;

예시: Top-K 스케치로 트렌드 항목 찾기

배치에 걸쳐 가장 자주 발생하는 항목을 추적해요.

-- 시간별 top-k 스케치를 저장할 테이블 만들기
CREATE TABLE hourly_search_sketches (
  hour_ts TIMESTAMP,
  search_sketch STRUCT<sketch: BINARY, maxItemsTracked: INT, itemDataType: STRING, itemDataTypeDDL: STRING>
) USING PARQUET;

-- 각 시간의 검색 쿼리 처리
INSERT INTO hourly_search_sketches
SELECT 
  DATE_TRUNC('hour', search_time) as hour_ts,
  approx_top_k_accumulate(search_term, 10000) as search_sketch
FROM search_logs
GROUP BY DATE_TRUNC('hour', search_time);

-- 조회: 특정 시간의 검색 상위 10개 구하기
SELECT approx_top_k_estimate(search_sketch, 10) as top_searches
FROM hourly_search_sketches
WHERE hour_ts = TIMESTAMP'2024-01-15 14:00:00';

-- 조회: 스케치를 결합해 하루 전체의 검색 상위 10개 구하기
SELECT approx_top_k_estimate(
  approx_top_k_combine(search_sketch, 10000),
  10
) as daily_top_searches
FROM hourly_search_sketches
WHERE DATE(hour_ts) = DATE'2024-01-15';

예시: Tuple 스케치로 집계 지표를 동반한 고유 사용자

Tuple 스케치는 고유 개수와 집계 지표를 동시에 추적할 수 있게 해줘요. 고유 사용자를 세면서 동시에 그들의 활동 지표를 합산하는 시나리오에 유용해요.

-- 사용자와 그들의 지출을 추적하는 일일 tuple 스케치 저장 테이블 만들기
CREATE TABLE daily_user_spend_sketches (
  event_date DATE,
  user_spend_sketch BINARY
) USING PARQUET;

-- 1일차: 고유 사용자와 총 지출 추적
INSERT INTO daily_user_spend_sketches
SELECT
  DATE'2024-01-01' as event_date,
  tuple_sketch_agg_double(user_id, purchase_amount) as user_spend_sketch
FROM purchases_day1;

-- 2일차: 다음 날의 사용자와 지출 추적
INSERT INTO daily_user_spend_sketches
SELECT
  DATE'2024-01-02' as event_date,
  tuple_sketch_agg_double(user_id, purchase_amount) as user_spend_sketch
FROM purchases_day2;

-- 조회: 하루의 고유 사용자와 총 지출 구하기
SELECT
  event_date,
  tuple_sketch_estimate_double(user_spend_sketch) as unique_users,
  tuple_sketch_summary_double(user_spend_sketch) as total_spend
FROM daily_user_spend_sketches
WHERE event_date = DATE'2024-01-01';

-- 조회: 일주일 동안의 고유 사용자와 총 지출 구하기(스케치 병합)
SELECT
  tuple_sketch_estimate_double(tuple_union_agg_double(user_spend_sketch)) as weekly_unique_users,
  tuple_sketch_summary_double(tuple_union_agg_double(user_spend_sketch)) as weekly_total_spend
FROM daily_user_spend_sketches
WHERE event_date BETWEEN DATE'2024-01-01' AND DATE'2024-01-07';

-- 조회: 1주차에는 구매했지만 2주차에는 구매하지 않은 사용자 찾기
WITH week1_sketch AS (
  SELECT tuple_union_agg_double(user_spend_sketch) as sketch
  FROM daily_user_spend_sketches
  WHERE event_date BETWEEN DATE'2024-01-01' AND DATE'2024-01-07'
),
week2_sketch AS (
  SELECT tuple_union_agg_double(user_spend_sketch) as sketch
  FROM daily_user_spend_sketches
  WHERE event_date BETWEEN DATE'2024-01-08' AND DATE'2024-01-14'
)
SELECT tuple_sketch_estimate_double(
  tuple_difference_double(
    (SELECT sketch FROM week1_sketch),
    (SELECT sketch FROM week2_sketch)
  )
) as churned_users;

-- 조회: 두 주 모두 구매한 사용자 찾기(교집합)
WITH week1_sketch AS (
  SELECT tuple_union_agg_double(user_spend_sketch) as sketch
  FROM daily_user_spend_sketches
  WHERE event_date BETWEEN DATE'2024-01-01' AND DATE'2024-01-07'
),
week2_sketch AS (
  SELECT tuple_union_agg_double(user_spend_sketch) as sketch
  FROM daily_user_spend_sketches
  WHERE event_date BETWEEN DATE'2024-01-08' AND DATE'2024-01-14'
)
SELECT
  tuple_sketch_estimate_double(
    tuple_intersection_double(
      (SELECT sketch FROM week1_sketch),
      (SELECT sketch FROM week2_sketch)
    )
  ) as retained_users;

-- 조회: theta 변형으로 등록 사용자(지출 포함)와 익명 방문자 결합
-- 이는 Tuple 스케치(지표 포함)와 Theta 스케치(ID만)를 병합하는 것을 보여줘요

-- 등록 사용자 구매와 익명 방문자 데이터가 모두 있다고 가정해요
CREATE TABLE registered_user_purchases (
  purchase_date DATE,
  user_purchase_sketch BINARY  -- Tuple 스케치: user_id with purchase_amount
) USING PARQUET;

CREATE TABLE anonymous_visitor_logs (
  visit_date DATE,
  visitor_sketch BINARY  -- Theta 스케치: visitor_id only
) USING PARQUET;

-- 조회: 총 고유 사용자(등록 + 익명)
SELECT
  tuple_sketch_estimate_double(
    tuple_union_theta_double(
      (SELECT user_purchase_sketch FROM registered_user_purchases WHERE purchase_date = DATE'2024-01-01'),
      (SELECT visitor_sketch FROM anonymous_visitor_logs WHERE visit_date = DATE'2024-01-01')
    )
  ) as total_unique_users;

-- 조회: 익명 방문자로도 나타난 등록 사용자 찾기
-- (예: 로그인한 후에도 익명으로 탐색한 사용자)
SELECT
  tuple_sketch_estimate_double(
    tuple_intersection_theta_double(
      (SELECT user_purchase_sketch FROM registered_user_purchases WHERE purchase_date = DATE'2024-01-01'),
      (SELECT visitor_sketch FROM anonymous_visitor_logs WHERE visit_date = DATE'2024-01-01')
    )
  ) as cross_session_users;

-- 조회: 결코 익명 방문자로 나타나지 않은 등록 사용자
-- (로그인한 상태에서만 사이트에 접속하는 사용자)
SELECT
  tuple_sketch_estimate_double(
    tuple_difference_theta_double(
      (SELECT user_purchase_sketch FROM registered_user_purchases WHERE purchase_date = DATE'2024-01-01'),
      (SELECT visitor_sketch FROM anonymous_visitor_logs WHERE visit_date = DATE'2024-01-01')
    )
  ) as logged_in_only_users,
  tuple_sketch_summary_double(
    tuple_difference_theta_double(
      (SELECT user_purchase_sketch FROM registered_user_purchases WHERE purchase_date = DATE'2024-01-01'),
      (SELECT visitor_sketch FROM anonymous_visitor_logs WHERE visit_date = DATE'2024-01-01')
    )
  ) as logged_in_only_revenue;

출처: 문서

더 알아보기 (Learn more)