数値インデックス

検索インデックスは、テキストのインデックス付けに加えて、数値のインデックス付けを効率的に行うことができます。主に数値フィールドに対する条件で全文検索クエリを拡張するために使用されます。このページでは、数値検索インデックスをテーブルに追加する方法と、配列をトークン化する方法について説明します。

概要

Spanner は、次のクエリ オペレーションでの数値のインデックス付けをサポートしています。

  • 等価comparison_type=>"equality"
  • 不等価comparison_type=>"all"

どちらの場合も、元の数値(整数または浮動小数点)に対してトークン化処理が行われます。これは、概念的には全文トークン化と類似しています。これにより、クエリで数値条件に一致するドキュメントを検索するために使用できるトークンのセットが生成されます。

等価インデックス付けでは、数値を表すトークンが 1 つだけ生成されます。このモードは、クエリに WHERE 句内で field = @p 形式の条件のみが含まれている場合におすすめします。

不等価と等価のインデックス付けを使用すると、クエリの WHERE 句でより幅広い条件を高速化できます。これには、等価条件に加えて、field < @pfield <= @pfield > @pfield >= @pfield BETWEEN @p1 and @p2field <> @p が含まれます。このタイプのインデックス付けを実装するために、Spanner は基盤となる検索インデックスにトークンを生成します。Spanner は、調整パラメータに応じて、インデックス付けされた数値ごとに多数のトークンを生成する場合があります。トークンの数は、TOKENIZE_NUMBER に設定されているパラメータ(algorithmminmaxgranularity など)によって異なります。したがって、調整パラメータを慎重に評価して、ディスク ストレージとルックアップ時間の適切なバランスを確保することが重要です。

数値範囲のインデックス付けのアルゴリズム

TOKENIZE_NUMBER algorithm 引数には、数値範囲にインデックスを付けるための 3 つのオプションがあります(logtreeprefixtreefloatingpoint)。各アルゴリズムは、特定のデータ分布とクエリ範囲のインデックス付けに適しています。

  • logtree は、整数を含む均一に分散された列にインデックスを付けるのに最適です。これがデフォルトのアルゴリズムです。
  • prefixtree は、指数関数的に分散されたデータのインデックス付けや、クエリの述語が「@param > number」または「@param >= number」(上限のない範囲)の形式である場合に最適です。logtree と比較して、このアルゴリズムは小さい数に対して生成されるインデックス トークンが少なくなります。WHERE 句に前述の述語が含まれているクエリの場合、prefixtree は生成されるクエリ トークンが少ないため、パフォーマンスが向上します。
  • floatingpoint は、インデックス付けされたデータとクエリに小数が含まれることが多い FLOAT64 値をインデックス付けする場合に最適です。他のアルゴリズムは整数のみをインデックス付けするため、小数範囲を対象とするクエリでは、一致しない値がより多く取得される可能性があります。これらの一致しない値は取得後にフィルタする必要があり、これはパフォーマンスに悪影響を及ぼします。logtreeprefixtree と比較した場合、このアルゴリズムでは、より多くのインデックス トークンが生成され、より多くのクエリトークンが生成される可能性があります。

base パラメータは、logtree アルゴリズムと prefixtree アルゴリズムの各ツリーバケットの幅を制御します。どちらのアルゴリズムも、ノードの幅が basedistance_from_leafbase 次元ツリー内のノードを表すトークンを生成します。これらのアルゴリズムの違いは、prefixtree が greater-than クエリを高速化する greater-than トークンを優先し、ツリー ノードの一部を省略する点です。選択したベースが大きいほど、生成されるインデックス トークンは少なくなります。ただし、base の値が大きいほど、必要なクエリトークンの最大数が増加します。

[min, max] の範囲外の数値はすべて、2 つのバケットにインデックス付けされます。1 つは min 未満の数値用で、もう 1 つは max より大きい数値用です。これにより、クエリによってリクエストされた範囲に範囲外の数値が含まれている場合も、かなりの過剰な取得(過剰な数値の取得)が発生する可能性があります。このため、minmax を、すべての入力数値を含む可能な限り狭い値に設定します。すべてのトークン化構成と同様に、min 値と max 値を変更するには数値インデックスを再構築する必要があるため、列の最終ドメインが不明な場合は、拡大する余地を残してください。検索プロセスの最後にすべての潜在的な一致がバケット化されていない数値と照合されるため、過剰取得の問題は正確性の問題ではありません。効率性の問題のみの可能性があります。

granularity 引数は、ツリーベースのアルゴリズムでインデックス付けされる前に数値に適用されるダウンサンプリング レートを制御します。各数値は、トークン化される前に、幅が granularity のバケットに並べ替えられます。同じ granularity バケット内の数値はすべて、同じトークンを取得します。つまり、粒度値が 1 以外に設定されていると、過剰な取得が発生する可能性があります。また、数値が少しだけ変化しても、ほとんどのトークンを再度インデックス付けする必要はありません。1 より大きい granularity を使用すると、アルゴリズムが生成する必要があるトークン数も減りますが、その効果は base を増やす場合ほど大きくありません。そのため、「粒度」は 1 に設定することをおすすめします。

配列のトークン化

TOKENIZE_NUMBER は、スカラー値に加えて、数値の配列のトークン化もサポートしています。

TOKENIZE_NUMBERARRAY 列で使用する場合は、comparison_type=>"equality" を指定する必要があります。範囲クエリは、数値の配列ではサポートされていません。

たとえば、次のスキーマを検討してみます。

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  Ratings ARRAY<INT64>,
  Ratings_Tokens TOKENLIST
    AS (TOKENIZE_NUMBER(Ratings, comparison_type=>"equality")) HIDDEN,
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex ON Albums(Grades_Tokens);

次のクエリは、評価が 1 または 2 のすべてのアルバムを検索します。

SELECT AlbumId
FROM Albums
WHERE ARRAY_CONTAINS_ANY(Ratings, [1, 2])

次のクエリは、1 と 5 と評価されたアルバムをすべて検索します。

SELECT AlbumId
FROM Albums
WHERE ARRAY_CONTAINS_ALL(Ratings, [1, 5])

次のステップ