スケッチ

GoogleSQL for BigQuery は、データスケッチをサポートしています。データスケッチは、データ集計のコンパクトな概要です。これには、集計情報の抽出、データ集計の継続、あるいは別のスケッチとの結合に必要な情報をすべてがキャプチャされ、再集計が可能になります。

スケッチを使用した指標の計算は、正確な値の計算よりも大幅に安価になります。計算が遅すぎる場合や一時ストレージが多くなりすぎる場合は、スケッチを使用してクエリの時間とリソースを削減します。

さらに、カーディナリティ(個別のユーザー数など)や変位値(訪問期間の中央値など)の計算をスケッチを使用せずに行うには、通常、元データに対してジョブを実行する必要があります。これは、すでに集計されたデータをこれ以上組み合わせることができないためです。

次のデータがあるテーブルについて考えます。

プロダクト ユーザー数 訪問時間の中央値
プロダクト 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
  );

スケッチでは元のデータを不可逆圧縮しているため、エラーの範囲または信頼区間(CI)で表される統計エラーが発生します。ほとんどのアプリケーションでは、この不確実度は小さくなります。たとえば、一般的なカーディナリティ計数スケッチの相対誤差は、すべてのケースの 95% に対し約 1% です。スケッチを使用すると、ある程度の精度(正確さ)低下と引き換えに、より速く、より低コストで計算でき、ストレージの使用量が減少します。

まとめると、スケッチには次のような主な特性があります。

  • 特定の指標の近似集計を表す
  • コンパクトである
  • メモリ内、劣線形データ構造のシリアル化された形式
  • 通常は固定サイズであり、入力よりも漸近的に小さくなる
  • 統計誤差を生じ、その程度は制度レベルで決定できる
  • 他のスケッチの結合で、基になるデータセットの結合を近似できる

スケッチの結合による再集計

スケッチにより、データを保存して結合することで、効率的な再集計が可能になります。このため、スケッチは、データセットのマテリアライズド ビューに特に役立ちます。スケッチを結合することにより、各ストリームに対して作成された部分的なスケッチを使用して複数のデータ ストリームの概要を作成できます。

たとえば、毎日個別ユーザーの推定数のスケッチを作成する場合、日ごとのスケッチを結合することで、過去 7 日間の個別ユーザーの数が得られます。結合した日ごとのスケッチを再集計すれば、データセットの全入力を読み取る必要はありません。

スケッチの再集計は、オンライン分析処理(OLAP)でも有用です。スケッチを結合して、OLAP キューブのロールアップを作成できます。ここで、スケッチには、キューブの 1 つ以上の特定のディメンションについてデータが要約されます。OLAP ロールアップは、実際の個別数では行えません。

使用すべきスケッチのタイプ

指標の種類にあわせて異なるスケッチ アルゴリズムが用意されています。たとえば、個別カウント用の HLL++ や、分位用の KLL があります。GoogleSQL には、精度などのクエリの詳細を指定することなく、このような種類のデータをクエリするために使用できる近似集計関数も用意されています。

使用するスケッチは、推定が必要なデータの種類によって異なります。

カーディナリティを推定する

カーディナリティを推定する必要がある場合は、HLL++ スケッチを使用します。

たとえば、ある月でプロダクトを積極的に使用したユニーク ユーザー数(MAU または 28DAU の指標)を取得するには、HLL++ スケッチを使用します。

分位を計算する

データセットの分位を取得する必要がある場合は、KLL スケッチを使用します。

たとえば、店舗での顧客の訪問時間の中央値を取得する場合や、キュー内にあるチケットが処理されるまでにかかったレイテンシの 95 パーセンタイル値を追跡する場合には、KLL スケッチを使用します。

HLL++ スケッチ

HyperLogLog++(HLL++)は、カーディナリティを推定するためのスケッチ アルゴリズムです。HLL++ は、論文 HyperLogLog in Practice に基づいており、「++」は HyperLogLog アルゴリズムに加えられた拡張を表しています。

カーディナリティとは、スケッチへの入力に含まれる個別要素の数のことです。たとえば、HLL++ スケッチを使用して、あるアプリを起動したユニーク ユーザーの数を取得できます。

HLL++ は、カーディナリティが非常に小さい場合や大きい場合にも推測できます。HLL++ アルゴリズムには、64 ビットハッシュ関数、低いカーディナリティの推測でメモリ要件を減らすためのスパース表現、および低いカーディナリティの推測の経験的バイアス補正が含まれています。

精度

HLL++ スケッチはカスタム精度をサポートしています。次の表に、サポートされる精度値、最大ストレージ サイズ、一般的な精度レベルの信頼区間(CI)を示します。

精度 最大ストレージ サイズ 65% CI 95% CI 99% CI
10 1 KiB + 28 B ±3.25% ±6.50% ±9.75%
11 2 KiB + 28 B ±2.30% ±4.60% ±6.89%
12 4 KiB + 28 B ±1.63% ±3.25% ±4.88%
13 8 KiB + 28 B ±1.15% ±2.30% ±3.45%
14 16 KiB + 30 B ±0.81% ±1.63% ±2.44%
15(デフォルト) 32 KiB + 30 B ±0.57% ±1.15% ±1.72%
16 64 KiB + 30 B ±0.41% ±0.81% ±1.22%
17 128 KiB + 30 B ±0.29% ±0.57% ±0.86%
18 256 KiB + 30 B ±0.20% ±0.41% ±0.61%
19 512 KiB + 30 B ±0.14% ±0.29% ±0.43%
20 1,024 KiB + 30 B ±0.10% ±0.20% ±0.30%
21 2,048 KiB + 32 B ±0.07% ±0.14% ±0.22%
22 4,096 KiB + 32 B ±0.05% ±0.10% ±0.15%
23 8,192 KiB + 32 B ±0.04% ±0.07% ±0.11%
24 16,384 KiB + 32 B ±0.03% ±0.05% ±0.08%

HLL++ スケッチの精度は、HLL_COUNT.INIT 関数で初期化するときに定義できます。

削除

HLL++ スケッチから値を削除することはできません。

補足情報

HLL++ スケッチで使用できる関数の一覧については、HLL++ 関数をご覧ください。

スケッチの統合

HLL++ スケッチを他のシステムと統合できます。たとえば、DataflowApache SparkZetaSketch などの外部アプリケーションで作成したスケッチを、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 を使用して中央値を検出する場合は、99.999% のケースで、KLL_QUANTILES.EXTRACT_POINT 関数によって返される値のランクは、実際のランクとは最大で n/100 異なる値になります。つまり、返される値はほぼ必ず、49~51 パーセンタイルの間に収まります。スケッチに 1,000,000 個のアイテムがある場合、返される中央値のランクはほぼ必ず、490,000~510,000 の間に収まります。

KLL スケッチの精度は、KLL_QUANTILES.INIT 関数で初期化するときに定義できます。

サイズ

KLL スケッチのサイズは、精度パラメータと入力タイプによって決まります。入力タイプが INT64 の場合、スケッチは追加の最適化を使用できます。これは、入力値が小さな母集団から取得される場合に特に役立ちます。次の表には、INT64 の列が 2 つ示されています。1 つ目の列には、サイズが 1 B の限定された母集団から取得されたアイテムのスケッチサイズの上限が示されており、2 つ目の列には、任意の入力値の上限が示されています。

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

ファイ

ファイ(Φ)は、スケッチ入力の合計行数の割合として生成される分位を表し、0~1 の間で正規化されています。関数がファイをサポートしている場合、関数は約 Φ * n の入力が v 以下になり、(1-Φ)* n の入力が v 以上になるような値 v を返します。

補足情報

KLL スケッチで使用できる関数の一覧は、KLL 分位関数をご覧ください。

KLL アルゴリズムは、論文 Optimal Quantile Approximation in Streams で定義されています。このアルゴリズムの名前は、2016 年にこの論文を発表した著者の Karnin、Lang、Liberty から付けられました。KLL アルゴリズムは、可変サイズのバッファを使用して大規模なデータセットのメモリ使用量を削減し、スケッチのサイズを O(log n) から O(1) に減らすことで、古い MP80 アルゴリズムを改良したものです。このアルゴリズムの非決定的な性質により、同じデータセットを基に、同じ精度で作成されたスケッチでも同じにはならない場合があります。

分位

分位は、確率分布の範囲を確率が等しい連続区間に分割する点です。または、サンプル内の観測値を同様に分割する点です。分位対応のスケッチを使用すると、これらの区間と確率を集計してほぼ正確な分位の結果を求めることで、分位を推定できます。

分位は通常、次の 2 つの方法で定義されます。

  • 正の整数 q の場合、q 分位は入力セットをほぼ同じサイズの q 個のサブセットに分割する値のセットです。これらの中には、特定の名称を持つものがあります。たとえば、単一の 2 分位は中央値、4 分位は四分位、100 分位はパーセンタイルです。KLL 関数はさらに、入力の(正確な)最小値と最大値を返すため、2 分位をクエリした場合は、3 つの値が返されます。

  • または、分位を個別の Φ 分位と考えることもできます。ここで、Φ0 <= Φ <= 1 である実数です。Φ 分位 x とは、入力のうち Φ の割合が x 以下で、(1-Φ) の割合が x 以上になるような入力の要素です。この考え方では、中央値は 0.5 分位であり、95 パーセンタイルは 0.95 分位です。

たとえば、分位対応のスケッチを使用して、ユーザーがアプリを開いた回数の中央値を取得できます。

近似集計関数

特定のスケッチベースの近似関数の代わりに、GoogleSQL では事前定義された近似集計関数が用意されています。これらの近似集計関数は、個別カウント、変位数、トップカウントなどの一般的な評価用のスケッチをサポートしていますが、カスタム精度は使用できません。また、他の種類のスケッチのように再集計するために公開されたり保存されたりすることはありません。近似集計関数は、詳細な構成を行わずに簡単なスケッチベースのクエリを実行するために設計されています。

スケッチベースの近似で使用できる近似集計関数の一覧については、近似集計関数をご覧ください。