스케치

BigQuery용 GoogleSQL은 데이터 스케치를 지원합니다. 데이터 스케치는 데이터 집계를 간결하게 요약한 것입니다. 이는 집계 결과를 추출하거나, 데이터 집계를 계속하거나, 다른 스케치와 병합하여 재집계를 수행하는 데 필요한 모든 정보를 캡처합니다.

스케치를 사용하여 측정항목을 계산하는 것은 정확한 값을 계산하는 것보다 비용이 훨씬 저렴합니다. 계산이 너무 느리거나 임시 스토리지가 너무 많이 필요한 경우 스케치를 사용하여 쿼리 시간과 리소스를 절약하세요.

또한 스케치가 없는 카디널리티(예: 고유 사용자 수) 또는 분위수(예: 방문 시간 중앙값) 계산의 경우에는 이미 집계된 데이터를 더 이상 결합할 수 없으므로 일반적으로 원시 데이터를 이용한 작업을 통해서만 수행할 수 있습니다.

다음 데이터가 포함된 테이블을 살펴보세요.

제품 사용자 수 방문 시간 중앙값
제품 A 5억 개 10분
제품 B 2,000만 개 2분

이 테이블에서 두 제품을 모두 사용한 사용자 수를 알 수 없으므로 두 제품의 총 사용자 수를 계산할 수 없습니다. 마찬가지로 방문 시간의 분포가 손실되었으므로 방문 시간의 중앙값을 계산할 수 없습니다.

해결책은 스케치를 테이블에 대신 저장하는 것입니다. 각 스케치는 특정 입력 속성(예: 카디널리티)을 대략적이고 간소하게 표현한 것으로서 저장, 병합(또는 재집계)하고 근접한 결과를 쿼리할 수 있습니다. 이전 예시에서는 제품마다 스케치를 만들고 병합(재집계)하여 제품 A와 제품 B의 고유 사용자 수를 추정할 수 있습니다. 마찬가지로 병합 및 쿼리 가능한 분위수 스케치를 사용하여 방문 시간 중앙값을 추정할 수도 있습니다.

예를 들어 다음 쿼리는 HLL++KLL 스케치를 사용하여 YouTube(제품 A) 및 Google 지도(제품 B)의 고유 사용자 수와 방문 시간 중앙값을 추정합니다.

-- Build sketches for YouTube stats.
CREATE TABLE user.YOUTUBE_ACCESS_STATS
AS
SELECT
  HLL_COUNT.INIT(user_id) AS distinct_users_sketch,
  KLL_QUANTILES.INIT_INT64(visit_duration_ms) AS visit_duration_ms_sketch,
  hour_of_day
FROM YOUTUBE_ACCESS_LOG()
GROUP BY hour_of_day;

-- Build sketches for Maps stats.
CREATE TABLE user.MAPS_ACCESS_STATS
AS
SELECT
  HLL_COUNT.INIT(user_id) AS distinct_users_sketch,
  KLL_QUANTILES.INIT_INT64(visit_duration_ms) AS visit_duration_ms_sketch,
  hour_of_day
FROM MAPS_ACCESS_LOG()
GROUP BY hour_of_day;

-- Query YouTube hourly stats.
SELECT
  HLL_COUNT.EXTRACT(distinct_users_sketch) AS distinct_users,
  KLL_QUANTILES.EXTRACT_POINT_INT64(visit_duration_ms_sketch, 0.5)
  AS median_visit_duration, hour_of_day
FROM user.YOUTUBE_ACCESS_STATS;

-- Query YouTube daily stats.
SELECT
  HLL_COUNT.MERGE(distinct_users_sketch),
  KLL_QUANTILES.MERGE_POINT_INT64(visit_duration_ms_sketch, 0.5)
  AS median_visit_duration, date
FROM user.YOUTUBE_ACCESS_STATS
GROUP BY date;

-- Query total stats across YouTube and Maps.
SELECT
  HLL_COUNT.MERGE(distinct_users_sketch) AS unique_users_all_services,
  KLL_QUANTILES.MERGE_POINT_INT64(visit_duration_ms_sketch, 0.5)
    AS median_visit_duration_all_services,
FROM
  (
    SELECT * FROM user.YOUTUBE_ACCESS_STATS
    UNION ALL
    SELECT * FROM user.MAPS_ACCESS_STATS
  );

스케치는 원본 데이터의 손실(lossy) 압축이기 때문에 오류 경계 또는 신뢰 구간(CI)으로 표현되는 통계 오류가 발생합니다. 대부분의 애플리케이션에는 이러한 불확실성이 작습니다. 예를 들어 일반적인 카디널리티 계산 스케치는 모든 사례의 95% 에서 약 1%의 상대적 오류를 갖습니다. 스케치는 빠른 계산, 저렴한 비용, 적은 저장용량을 위해 정확성 또는 정밀도를 어느 정도 포기합니다.

요약하면 스케치에는 다음과 같은 기본 속성이 있습니다.

  • 특정 측정항목의 근사치 집계를 나타냅니다.
  • 간결합니다.
  • 메모리 내 저선형 데이터 구조의 직렬화된 형식입니다.
  • 일반적으로 크기가 고정되며 입력보다 점근적으로 더 작습니다.
  • 정밀도 수준에 따라 확인 가능한 통계 오류가 발생할 수 있습니다.
  • 다른 스케치와 병합하여 기본 데이터 세트의 합집합을 요약합니다.

스케치 병합을 통한 재집계

스케치에서는 효율적인 재집계를 위해 데이터를 저장하고 병합할 수 있습니다. 그 결과 스케치가 데이터 세트의 구체화된 뷰에 특히 유용합니다. 스케치를 병합하면 각 스트림에 생성된 부분 스케치를 기반으로 여러 데이터 스트림을 요약할 수 있습니다.

예를 들어 매일 예상되는 고유 사용자 수의 스케치를 만드는 경우 일일 스케치를 병합하여 지난 7일간의 고유 사용자 수를 가져올 수 있습니다. 병합된 일일 스케치를 다시 집계하면 데이터 세트의 전체 입력 읽기를 방지하는 데 도움이 됩니다.

스케치 재집계는 온라인 분석 처리(OLAP)에도 유용합니다. 스케치를 병합하여 OLAP 큐브의 롤업을 만들 수 있습니다. 여기에서 스케치가 큐브의 특정 차원 하나 이상을 따라 데이터를 요약합니다. OLAP 롤업은 참 고유 수 집계로는 불가능합니다.

어떤 유형의 스케치를 사용해야 하나요?

다양한 스케치 알고리즘은 고유 개수의 경우 HLL++, 분위수의 경우 KLL 등 다양한 유형의 측정항목에 맞게 설계됩니다. 또한 GoogleSQL은 정밀도 수준과 같은 쿼리 세부정보를 지정하지 않고도 이러한 유형의 데이터를 쿼리하는 데 사용할 수 있는 근사치 집계 함수를 제공합니다.

사용하는 스케치는 추정해야 하는 데이터 유형에 따라 다릅니다.

카디널리티 추정

카디널리티를 추정해야 하는 경우 HLL++ 스케치를 사용하세요.

예를 들어 특정 월에 제품을 적극적으로 사용한 순 사용자 수(MAU 또는 28DAU 측정항목)를 가져오려면 HLL++ 스케치를 사용합니다.

분위수 계산

데이터 세트의 분위수를 구해야 하는 경우 KLL 스케치를 사용하세요.

예를 들어 매장에서 고객의 방문 시간 중앙값을 구하거나 티켓이 해결되기 전에 대기열에 머무는 95번째 백분위수 지연 시간을 추적하려면 KLL 스케치를 사용하세요.

HLL++ 스케치

HyperLogLog++(HLL++)는 카디널리티 추정을 위한 스케치 알고리즘입니다. HLL++는 HyperLogLog 실무 자료를 기반으로 하며, 여기서 ++는 HyperLogLog 알고리즘에 적용된 증강을 나타냅니다.

카디널리티는 스케치 입력의 고유 요소 수입니다. 예를 들어 HLL++ 스케치를 사용하여 애플리케이션을 연 순 사용자 수를 가져올 수 있습니다.

HLL++는 매우 작거나 큰 카디널리티를 추정합니다. HLL++에는 64비트 해시 함수, 작은 카디널리티 추정치의 메모리 요구사항 완화를 위한 희소 표현, 작은 카디널리티 추정치에 대한 경험적 편향 수정이 포함됩니다.

정밀도

HLL++ 스케치는 커스텀 정밀도를 지원합니다. 다음 표는 지원되는 정밀도 값, 최대 스토리지 크기, 일반적 정밀도 수준의 신뢰 구간(CI)을 보여 줍니다.

정밀도 최대 스토리지 크기 65% CI 95% CI 99% CI
10 1KiB + 28B ±3.25% ±6.50% ±9.75%
11 2KiB + 28B ±2.30% ±4.60% ±6.89%
12 4KiB + 28B ±1.63% ±3.25% ±4.88%
13 8KiB + 28B ±1.15% ±2.30% ±3.45%
14 16KiB + 30B ±0.81% ±1.63% ±2.44%
15(기본값) 32KiB + 30B ±0.57% ±1.15% ±1.72%
16 64KiB + 30B ±0.41% ±0.81% ±1.22%
17 128KiB + 30B ±0.29% ±0.57% ±0.86%
18 256KiB + 30B ±0.20% ±0.41% ±0.61%
19 512KiB + 30B ±0.14% ±0.29% ±0.43%
20 1,024KiB + 30B ±0.10% ±0.20% ±0.30%
21 2,048KiB + 32B ±0.07% ±0.14% ±0.22%
22 4,096KiB + 32B ±0.05% ±0.10% ±0.15%
23 8,192KiB + 32B ±0.04% ±0.07% ±0.11%
24 16,384KiB + 32B ±0.03% ±0.05% ±0.08%

HLL++ 스케치를 HLL_COUNT.INIT 함수로 초기화할 때 스케치의 정밀도를 정의할 수 있습니다.

삭제

HLL++ 스케치에서 값을 삭제할 수 없습니다.

추가 세부정보

HLL++ 스케치와 함께 사용할 수 있는 함수 목록은 HLL++ 함수를 참조하세요.

스케치 통합

HLL++ 스케치를 다른 시스템과 통합할 수 있습니다. 예를 들어 Dataflow, Apache Spark, ZetaSketch와 같은 외부 애플리케이션에서 스케치를 빌드한 후 GoogleSQL에서 사용하거나 그 반대로도 할 수 있습니다.

GoogleSQL 외에도 Java에서 HLL++ 스케치를 사용할 수 있습니다.

KLL 스케치

KLL(Karnin-Lang-Liberty의 약어)은 대략적인 분위수의 스케치를 계산하는 스트리밍 알고리즘입니다. 소수의 근사치 오류를 감수하고 정확한 계산보다 훨씬 더 효율적으로 임의의 분위수를 계산합니다.

정밀도

KLL 스케치는 커스텀 정밀도를 지원합니다. 정밀도는 반환된 근사 분위수 q의 정확성을 정의합니다.

기본적으로 근사 분위수의 순위는 ⌈Φ * n⌉로부터 최대 ±1/1000 * n만큼 벗어날 수 있습니다. 여기서 n은 입력의 행 수이고 ⌈Φ * n⌉은 정확한 중앙값의 순위입니다.

커스텀 정밀도를 제공하면 근사 분위수의 순위가 정확한 분위수의 순위에서 최대 ±1/precision * n만큼 벗어날 수 있습니다. 99.999%의 경우 오류가 이 오류 경계 내에 있습니다. 이 오류 보장은 정확한 순위와 대략적인 순위 간의 차이에만 적용됩니다. 분위수의 정확한 값과 근사치 간의 수치 차이는 임의로 클 수 있습니다.

예를 들어 중앙값 Φ = 0.5를 찾고 기본 정밀도 1000을 사용한다고 가정해 보겠습니다. 그러면 KLL_QUANTILES.EXTRACT_POINT 함수에서 반환하는 값의 순위는 99.999%의 경우 실제 순위와 최대 n/1000만큼 다릅니다. 즉, 반환된 값은 거의 항상 49.9번째와 50.1번째 백분위수 사이입니다. 스케치에 항목이 1,000,000개 있는 경우 반환된 중앙값의 순위는 거의 항상 499,000~501,000 사이입니다.

커스텀 정밀도 100을 사용하여 중앙값을 찾는 경우 KLL_QUANTILES.EXTRACT_POINT 함수에서 반환된 값의 순위는 99.999%의 경우 실제 순위와 최대 n/100만큼 다릅니다. 즉, 반환된 값은 거의 항상 49번째와 51번째 백분위수 사이입니다. 스케치에 항목이 1,000,000개 있는 경우 반환된 중앙값의 순위는 거의 항상 490,000~510,000 사이입니다.

KLL 스케치를 KLL_QUANTILES.INIT 함수로 초기화할 때 KLL 스케치의 정밀도를 정의할 수 있습니다.

크기

KLL 스케치 크기는 정밀도 파라미터와 입력 유형에 따라 다릅니다. 입력 유형이 INT64인 경우 스케치는 입력 값이 작은 범위에서 가져온 경우에 특히 유용한 추가 최적화를 사용할 수 있습니다. 다음 표에는 INT64의 열이 두 개 포함되어 있습니다. 한 열은 크기가 1B인 제한된 범위의 항목에 대한 스케치 크기의 상한을 제공하고, 다른 열은 임의의 입력 값에 대한 상한을 제공합니다.

정밀도 FLOAT64 INT64(<1B) INT64(모든 유형)
10 761B 360B 717B
20 1.46KB 706B 1.47KB
50 3.49KB 1.72KB 3.60KB
100 6.94KB 3.44KB 7.12KB
200 13.87KB 6.33KB 13.98KB
500 35.15KB 14.47KB 35.30KB
1000 71.18KB 27.86KB 71.28KB
2000 144.51KB 55.25KB 144.57KB
5000 368.87KB 139.54KB 368.96KB
10000 749.82KB 282.27KB 697.80KB
20000 1.52MB 573.16KB 1.37MB
50000 3.90MB 1.12MB 3.45MB
100000 7.92MB 2.18MB 6.97MB

파이

파이(Φ)는 스케치 입력의 총 행 수에 대한 비율로 생성할 분위수를 나타내며 0과 1 사이로 정규화됩니다. 함수가 파이를 지원하는 경우 함수는 대략 Φ * n 입력이 v 이하이고(1-Φ) * n 입력이 v 이상이 되도록 값 v를 반환합니다.

추가 세부정보

KLL 스케치와 함께 사용할 수 있는 함수 목록은 KLL 분위수 함수를 참고하세요.

KLL 알고리즘은 스트림의 최적 분위수 근사치 논문에 정의되어 있으며, 2016년에 이 논문을 게시한 저자인 카닌, 랑, 리버티의 이름을 따서 명명되었습니다. KLL 알고리즘은 가변 크기 버퍼를 사용하여 대규모 데이터 세트의 메모리 사용량을 줄여 스케치 크기를 O(log n)에서 O(1)로 줄임으로써 이전 MP80 알고리즘을 개선합니다. 알고리즘의 비결정론적 특성으로 인해 동일한 데이터 세트에서 동일한 정밀도로 생성된 스케치는 동일하지 않을 수 있습니다.

분위수

분위수는 확률 분포의 범위를 동일한 확률의 연속 간격으로 나누거나 샘플의 관측값을 동일한 방식으로 나누는 절단점입니다. 분위수를 지원하는 스케치를 사용하면 이러한 간격과 확률을 거의 정확한 분위수 결과로 요약하여 분위수를 추정할 수 있습니다.

분위수는 일반적으로 다음 두 가지 방법으로 정의됩니다.

  • 양의 정수 q의 경우 q-분위수는 입력 집합을 거의 동일한 크기의 q개 하위 집합으로 분할하는 값 집합입니다. 이 중 일부는 특정한 이름을 갖습니다. 단일 2-분위수는 중앙값, 4-분위수는 사분위수, 100-분위수는 백분위수입니다. KLL 함수는 입력의 (정확한) 최솟값과 최댓값도 반환하므로 2-분위수를 쿼리하면 세 개의 값이 반환됩니다.

  • 또는 분위수를 개별 Φ-분위수로 간주할 수 있습니다. 여기서 Φ0 <= Φ <= 1의 실수입니다. Φ-분위수 x는 입력의 Φ 비율이 x보다 작거나 같고 (1-Φ) 비율이 x보다 크거나 같은 입력의 요소입니다. 이 표기법에서 중앙값은 0.5-분위수이고 95번째 백분위수는 0.95-분위수입니다.

예를 들어 분위수를 지원하는 스케치를 사용하여 사용자가 애플리케이션을 연 횟수의 중앙값을 가져올 수 있습니다.

근사치 집계 함수

특정 스케치 기반의 근사치 함수 대신 GoogleSQL은 사전 정의된 근사치 집계 함수를 제공합니다. 이러한 근사치 집계 함수는 고유 개수, 분위수, 최상위 개수와 같은 일반적인 추정을 위한 스케치를 지원하지만 커스텀 정밀도를 허용하지 않습니다. 또한 다른 유형의 스케치와 같이 재집계를 위한 스케치를 노출하고 저장하지 않습니다. 근사치 집계 함수는 자세한 구성 없이 빠른 스케치 기반 쿼리 실행을 위해 설계되었습니다.

스케치 기반 근사치에 사용할 수 있는 근사치 집계 함수 목록은 근사치 집계 함수를 참조하세요.