ベクトル インデックスを管理する

この機能に関するフィードバックやサポートのリクエストを行う場合は、bq-vector-search@google.com 宛てにメールを送信してください。

このドキュメントでは、ベクトル インデックスを作成および管理する方法について説明します。

ベクトル インデックスは、VECTOR_SEARCH 関数でエンベディングのより効率的なベクトル検索を実行できるようにするために設計されたデータ構造です。VECTOR_SEARCH でベクトル インデックスを使用できる場合、この関数は近似最近傍検索手法を使用して検索のパフォーマンスを向上させます。ただし、再現率を低減し、より近似的な結果を返すというトレードオフがあります。

ロールと権限

ベクトル インデックスを作成するには、インデックスを作成するテーブルに対する bigquery.tables.createIndex IAM 権限が必要です。ベクトル インデックスを削除するには、bigquery.tables.deleteIndex 権限が必要です。次の IAM 事前定義ロールには、ベクトル インデックスの操作に必要な権限が含まれています。

  • BigQuery データオーナー(roles/bigquery.dataOwner
  • BigQuery データ編集者(roles/bigquery.dataEditor

ベクトル インデックスを作成する

ベクトル インデックスを作成するには、CREATE VECTOR INDEX データ定義言語(DDL)ステートメントを使用します。

  1. [BigQuery] ページに移動します。

    [BigQuery] に移動

  2. クエリエディタでインデックス タイプを選択し、次のいずれかの SQL ステートメントを実行します。

    IVF ベクトル インデックスを作成するには:

    CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME
    ON DATASET_NAME.TABLE_NAME(COLUMN_NAME)
    STORING(STORED_COLUMN_NAME [, ...])
    OPTIONS(index_type = "IVF",
      distance_type = "DISTANCE_TYPE",
      ivf_options = '{"num_lists":NUM_LISTS}')
    

    TreeAH ベクトル インデックスを作成するには:

    CREATE [ OR REPLACE ] VECTOR INDEX [ IF NOT EXISTS ] INDEX_NAME
    ON DATASET_NAME.TABLE_NAME(COLUMN_NAME)
    OPTIONS(index_type = "TREE_AH",
      distance_type = "DISTANCE_TYPE",
      tree_ah_options = '{"leaf_node_embedding_count":LEAF_NODE_EMBEDDING_COUNT,
        "normalization_type":"NORMALIZATION_TYPE"}')
    

    詳しくは、ベクター インデックスのタイプを選択するをご覧ください。

    次のように置き換えます。

    • INDEX_NAME: 作成するベクトル インデックスの名前。インデックスは常にベーステーブルと同じプロジェクトとデータセットに作成されるため、名前にこれらを指定する必要はありません。
    • DATASET_NAME: テーブルを含むデータセットの名前。
    • TABLE_NAME: エンベディング データを持つ列を含むテーブルの名前。
    • COLUMN_NAME: エンベディング データを含む列の名前。列の型は ARRAY<FLOAT64> にする必要があります。この列に子フィールドを含めることはできません。配列内のすべての要素は非 NULL でなければならず、列の値はすべて同じ配列ディメンションでなければなりません。
    • STORED_COLUMN_NAME: ベクトル インデックスに格納するテーブルの最上位列の名前。列の型は RANGE にすることはできません。テーブルに行レベルのアクセス ポリシーが設定されている場合や、列にポリシータグが設定されている場合、保存された列は使用されません。保存された列を有効にする方法については、列を保存して事前フィルタするをご覧ください。
    • DISTANCE_TYPE: このインデックスを使用してベクトル検索を行う際に使用するデフォルトの距離の種類を指定します。サポートされている値は、EUCLIDEANCOSINEDOT_PRODUCT です。デフォルトは EUCLIDEAN です。

      インデックスの作成自体では、トレーニングに常に EUCLIDEAN 距離を使用しますが、VECTOR_SEARCH 関数で使用される距離は異なる場合があります。

      VECTOR_SEARCH 関数の distance_type 引数に値を指定すると、DISTANCE_TYPE 値の代わりにその値が使用されます。

    • NUM_LISTS: IVF アルゴリズムが作成するリストの数を決定する、5,000 以下の INT64 値。IVF アルゴリズムは、データ空間全体を NUM_LISTS に等しい複数のリストに分割します。データポイントが互いに近いほど、同じリストに入る可能性が高くなります。NUM_LISTS が小さい場合、リスト数が少なくなってそれぞれのデータポイント数が多くなり、値が大きい場合、リスト数が多くなってそれぞれのデータポイント数が少なくなります。

      NUM_LISTSVECTOR_SEARCH 関数の fraction_lists_to_search 引数と組み合わせて使用すると、効率的なベクトル検索を作成できます。エンベディング空間内の多数の小さなグループにデータが分散している場合、NUM_LISTS に大きな値を指定することでより多くのリストを持つインデックスを作成し、fraction_lists_to_search により小さな値を指定することでベクトル検索でスキャンするリストの数を減らします。データが少数の大きなグループに分散している場合は、NUM_LISTS に小さい値を、fraction_lists_to_search に大きい値を使用します。num_lists の値が大きいと、ベクトル インデックスの構築に時間がかかることがあります。

      NUM_LISTS を指定しない場合、BigQuery によって適切な値が計算されます。

    • LEAF_NODE_EMBEDDING_COUNT: 500 以上の INT64 値。TreeAH アルゴリズムが作成するツリーの各リーフノードにあるベクトルの概数を指定します。TreeAH アルゴリズムは、データ空間全体を複数のリストに分割します。各リストには約 LEAF_NODE_EMBEDDING_COUNT 個のデータポイントが含まれます。値が小さいほど、リスト数は増えますが、データポイント数は少なくなります。値が大きいほど、リスト数は減りますが、データポイント数は多くなります。デフォルトは 1,000 です。

    • NORMALIZATION_TYPE: STRING の値サポートされている値は、NONE or L2 です。デフォルトは NONE です。処理の前にベーステーブルのデータとクエリデータの両方に正規化が実行されますが、TABLE_NAME の埋め込み列 COLUMN_NAME は変更されません。データセット、エンベディング モデル、VECTOR_SEARCH で使用される距離タイプによっては、エンベディングの正規化で再現率が向上する場合があります。

次の例では、my_tableembedding 列にベクトル インデックスを作成します。

CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>);

CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
OPTIONS(index_type = 'IVF');

次の例では、my_tableembedding 列にベクトル インデックスを作成し、使用する距離の種類と IVF オプションを指定しています。

CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>);

CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
OPTIONS(index_type = 'IVF', distance_type = 'COSINE',
ivf_options = '{"num_lists": 2500}')

次の例では、my_tableembedding 列にベクトル インデックスを作成し、使用する距離の種類と TreeAH オプションを指定しています。

CREATE TABLE my_dataset.my_table(id INT64, embedding ARRAY<FLOAT64>);

CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
OPTIONS (index_type = 'TREE_AH', distance_type = 'EUCLIDEAN',
tree_ah_options = '{"normalization_type": "L2"}');

ベクトル インデックスのタイプを選択する

BigQuery には 2 種類のベクトル インデックス タイプがあります。

IVF インデックス

IVF は反転ファイル インデックスです。K 平均法アルゴリズムを使用してベクトルデータをクラスタ化し、それに基づいてベクトルデータを分割します。VECTOR_SEARCH 関数を使用してベクトルデータを検索する場合、これらのパーティションを使用することで、判別するために読み取る必要のあるデータ量を削減できます。

TreeAH インデックス

TreeAH は、Google の ScaNN アルゴリズムを使用するベクトル インデックスの一種です。機能は次のとおりです。

  • ベーステーブルは、より小さく管理しやすいシャードに分割されます。

  • クラスタリング モデルがトレーニングされ、クラスタの数は tree_ah_optionsleaf_node_embedding_count オプションから取得されます。

  • ベクトルは直積量子化され、インデックス テーブルに格納されます。

  • VECTOR_SEARCH では、近似距離計算用にハードウェアで最適化された非対称ハッシュを使用して、各クエリベクトルの候補リストが効率的に計算されます。これらの候補は、正確なエンベディングを使用して再スコアリングされ、再ランク付けされます。

TreeAH アルゴリズムは、数百のクエリベクトルを処理するバッチクエリ用に最適化されています。直積量子化を使用すると、レイテンシとコストを大幅に削減できます。IVF と比較して数桁も削減できる可能性があります。ただし、オーバーヘッドが増加するため、クエリベクトルの数が少ない場合は IVF アルゴリズムのほうが適している場合があります。

ユースケースが次の条件を満たしている場合は、TreeAH インデックス タイプを試すことをおすすめします。

  • テーブルに含まれる行数が 2 億行以下。

  • 数百以上のクエリベクトルが関係する大規模なバッチクエリを頻繁に実行する。

    小規模なバッチクエリの場合、TreeAH インデックス タイプを使用する VECTOR_SEARCH はブルート フォースにフォールバックすることがあります。その場合、ベクトル インデックスが使用されない理由が挿入され、理由の説明が提供されます。

  • ワークフローで保存された列や事前フィルタリングを使用する必要がない。BigQuery は、TreeAH インデックスで使用されるプリフィルタをポストフィルタとして扱います。

スケーラビリティ、上限、パフォーマンスなどに関するお問い合わせは、bq-vector-search@google.com までお送りください。

列を保存して事前にフィルタする

ベクトル インデックスの効率をさらに高めるには、ベクトル インデックスに格納するベーステーブルの列を指定します。保存列を使用すると、VECTOR_SEARCH 関数を呼び出すクエリを次のように最適化できます。

  • VECTOR_SEARCH 関数は、ベーステーブルのすべての列を含む base という構造体を出力します。保存された列がないと、base に保存されている列を取得するために、結合が必要になる可能性があります。この処理には費用が発生します。クエリで base から保存された列のみを選択する場合、BigQuery はクエリを最適化して結合を排除します。

  • テーブル全体を検索する代わりに、WHERE 句を使用してベーステーブルを事前フィルタするクエリ ステートメントで VECTOR_SEARCH 関数を呼び出すことができます。テーブルにインデックスがあり、保存されている列のみでフィルタする場合、BigQuery は検索前にデータをフィルタし、インデックスを使用してより小さな結果セットを検索することでクエリを最適化します。保存されていない列でフィルタする場合、BigQuery はテーブルの検索後にフィルタを適用します(後処理フィルタ)。

    後処理フィルタは効率が低く、結果セット内の一致が top_k 未満になる可能性があります。場合によっては、事前フィルタによって結果セットのサイズが小さくなることもあります。その場合は、VECTOR_SEARCH の呼び出しで fraction_lists_to_search の値を増やしてみてください。

列を保存するには、CREATE VECTOR INDEX DDL ステートメントSTORING 句に列を指定します。列を保存するとベクトル インデックスのサイズが大きくなるため、頻繁に使用される列またはフィルタされた列のみを保存することをおすすめします。

次の例では、格納された列でベクタトル インデックスを作成して、さまざまなベクトル検索の動作について説明します。

-- Create a table that contains an embedding.
CREATE TABLE my_dataset.my_table(embedding ARRAY<FLOAT64>, type STRING, creation_time DATETIME, id INT64);

-- Create a query table that contains an embedding.
CREATE TABLE my_dataset.my_testdata(embedding ARRAY<FLOAT64>, test_id INT64);

-- Create a vector index with stored columns.
CREATE VECTOR INDEX my_index ON my_dataset.my_table(embedding)
STORING (type, creation_time)
OPTIONS (index_type = 'IVF');

-- Select only stored columns from a vector search to avoid an expensive join.
SELECT query, base.type, distance
FROM
  VECTOR_SEARCH(
    TABLE my_dataset.my_table,
    'embedding'
    TABLE my_dataset.my_testdata);

-- Pre-filter on a stored column. The index speeds up the query.
SELECT *
FROM
  VECTOR_SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE type = 'animal'),
    'embedding',
    TABLE my_dataset.my_testdata);

-- Filter on a column that isn't stored. The index is used to search the
-- entire table, and then the results are post-filtered. You might see fewer
-- than 5 matches returned for some embeddings.
SELECT query.test_id, base.type, distance
FROM
  VECTOR_SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE id = 123),
    'embedding',
    TABLE my_dataset.my_testdata,
    top_k => 5);

-- Use post-filters. The index is used, but the entire table is searched and
-- the post-filtering might reduce the number of results.
SELECT query.test_id, base.type, distance
FROM
  VECTOR_SEARCH(
    TABLE my_dataset.my_table,
    'embedding',
    TABLE my_dataset.my_testdata,
    top_k => 5)
WHERE base.type = 'animal';

-- Use pre-filters with brute force. The data is filtered and then searched
-- with brute force for exact results.
SELECT query.test_id, base.type, distance
FROM
  VECTOR_SEARCH(
    (SELECT * FROM my_dataset.my_table WHERE id = 123),
    'embedding',
    TABLE my_dataset.my_testdata,
    options => '{"use_brute_force":true}');

制限事項

  • 事前フィルタで論理ビューを使用できません。
  • 事前フィルタにサブクエリが含まれていると、インデックスを使用できない場合があります。
  • ベーステーブルで列のモード、タイプ、スキーマが変更され、その列がベクトル インデックスに格納されている場合、その変更がベクトル インデックスに反映されるまでに遅延が生じることがあります。更新がインデックスに適用されるまで、ベクトル検索クエリはベーステーブル内の変更された保存列を使用します。
  • 保存された列を持つインデックスのあるテーブルに対して、VECTOR_SEARCH クエリの query 出力から STRUCT 型の列を選択すると、クエリ全体が失敗する可能性があります。
  • プレビュー版の TreeAH インデックスでは、保存された列はサポートされていません。

インデックスの更新について

ベクトル インデックスは BigQuery によって完全に管理され、インデックス付きテーブルが変更されると自動的に更新されます。テーブル内のインデックス付き列を削除するか、テーブル自体の名前を変更すると、ベクトル インデックスは自動的に削除されます。

10 MB 未満のテーブルにベクトル インデックスを作成すると、ベクトル インデックスにはデータが挿入されません。同様に、インデックス付きテーブルからデータを削除してテーブルサイズが 10 MB を下回るようになった場合、ベクトル インデックスは一時的に無効になります。この場合、ベクトル検索クエリではインデックスが使用されず、Job リソースの vectorSearchStatistics セクションにある indexUnusedReasons コードは BASE_TABLE_TOO_SMALL になります。インデックスがない場合、VECTOR_SEARCH は自動的にブルート フォースを使用してエンベディングの最近傍を検出します。

VECTOR_SEARCH 関数を使用するクエリは、データの一部にまだインデックスが付いていない場合でも、常に正しい結果を返します。

ベクトル インデックスに関する情報を取得する

INFORMATION_SCHEMA をクエリすることで、ベクトル インデックスの存在と準備状況を確認できます。次のビューには、ベクトル インデックスのメタデータが含まれます。

  • INFORMATION_SCHEMA.VECTOR_INDEXES ビューには、データセット内のベクトル インデックスに関する情報が含まれます。

    CREATE VECTOR INDEX ステートメントが完了した後も、インデックスを使用するにはインデックスにデータが入力されている必要があります。last_refresh_time 列と coverage_percentage 列を使用して、ベクトル インデックスの準備状況を確認できます。ベクトル インデックスの準備ができていない場合でも、テーブルに対して VECTOR_SEARCH 関数を使用できますが、インデックスがない場合には実行速度が遅くなる可能性があります。

  • INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS ビューには、データセット内のすべてのテーブルについてのベクトル インデックス付き列に関する情報が含まれます。

  • INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS ビューには、データセット内のベクトル インデックスで使用されているオプションに関する情報が含まれています。

ベクトル インデックスの例

次の例では、プロジェクト my_project にあるデータセット my_dataset 内のテーブルに対するアクティブなベクトル インデックスがすべて表示されます。これには、名前、作成に使用された DDL ステートメント、カバレッジの割合が含まれます。インデックス付きベーステーブルが 10 MB 未満の場合、そのインデックスにはデータが取り込まれず、coverage_percentage 値は 0 になります。

SELECT table_name, index_name, ddl, coverage_percentage
FROM my_project.my_dataset.INFORMATION_SCHEMA.VECTOR_INDEXES
WHERE index_status = 'ACTIVE';

次のような結果になります。

+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table_name | index_name | ddl                                                                                             | coverage_percentage |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table1     | indexa     | CREATE VECTOR INDEX `indexa` ON `my_project.my_dataset.table1`(embeddings)                      | 100                 |
|            |            | OPTIONS (distance_type = 'EUCLIDEAN', index_type = 'IVF', ivf_options = '{"num_lists": 100}')   |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table2     | indexb     | CREATE VECTOR INDEX `indexb` ON `my_project.my_dataset.table2`(vectors)                         | 42                  |
|            |            | OPTIONS (distance_type = 'COSINE', index_type = 'IVF', ivf_options = '{"num_lists": 500}')      |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+
| table3     | indexc     | CREATE VECTOR INDEX `indexc` ON `my_project.my_dataset.table3`(vectors)                         | 98                  |
|            |            | OPTIONS (distance_type = 'DOT_PRODUCT', index_type = 'TREE_AH',                                 |                     |
|            |            |          tree_ah_options = '{"leaf_node_embedding_count": 1000, "normalization_type": "NONE"}') |                     |
+------------+------------+-------------------------------------------------------------------------------------------------+---------------------+

ベクトル インデックス列の例

次のクエリは、ベクトル インデックスを持つ列の情報を抽出します。

SELECT table_name, index_name, index_column_name, index_field_path
FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_COLUMNS;

次のような結果になります。

+------------+------------+-------------------+------------------+
| table_name | index_name | index_column_name | index_field_path |
+------------+------------+-------------------+------------------+
| table1     | indexa     | embeddings        | embeddings       |
| table2     | indexb     | vectors           | vectors          |
| table3     | indexc     | vectors           | vectors          |
+------------+------------+-------------------+------------------+

ベクトル インデックス オプションの例

次のクエリは、ベクトル インデックス オプションに関する情報を抽出します。

SELECT table_name, index_name, option_name, option_type, option_value
FROM my_project.dataset.INFORMATION_SCHEMA.VECTOR_INDEX_OPTIONS;

次のような結果になります。

+------------+------------+------------------+------------------+-------------------------------------------------------------------+
| table_name | index_name | option_name      | option_type      | option_value                                                      |
+------------+------------+------------------+------------------+-------------------------------------------------------------------+
| table1     | indexa     | index_type       | STRING           | IVF                                                               |
| table1     | indexa     | distance_type    | STRING           | EUCLIDEAN                                                         |
| table1     | indexa     | ivf_options      | STRING           | {"num_lists": 100}                                                |
| table2     | indexb     | index_type       | STRING           | IVF                                                               |
| table2     | indexb     | distance_type    | STRING           | COSINE                                                            |
| table2     | indexb     | ivf_options      | STRING           | {"num_lists": 500}                                                |
| table3     | indexc     | index_type       | STRING           | TREE_AH                                                           |
| table3     | indexc     | distance_type    | STRING           | DOT_PRODUCT                                                       |
| table3     | indexc     | tree_ah_options  | STRING           | {"leaf_node_embedding_count": 1000, "normalization_type": "NONE"} |
+------------+------------+------------------+------------------+-------------------------------------------------------------------+

ベクトル インデックスの使用

ベクトル インデックスの使用状況に関する情報は、ベクトル検索クエリを実行したジョブのジョブ メタデータで確認できます。ジョブ メタデータを表示するには、Google Cloud コンソール、bq コマンドライン ツール、BigQuery API、またはクライアント ライブラリを使用します。

Google Cloud コンソールを使用する場合、[ベクター インデックス使用モード] フィールドと [ベクター インデックスが使用されない理由] フィールドにベクトル インデックスの使用状況に関する情報が表示されます。

bq ツールまたは BigQuery API を使用する場合は、Job リソースの VectorSearchStatistics セクションでベクトル インデックスの使用状況に関する情報を確認できます。

インデックス使用モードは、次のいずれかの値により、ベクトル インデックスが使用されたかどうかを示します。

  • UNUSED: ベクトル インデックスは使用されていません。
  • PARTIALLY_USED: クエリ内の VECTOR_SEARCH 関数の中には、ベクトル インデックスを使用したものと使用しなかったものがあります。
  • FULLY_USED: クエリ内のすべての VECTOR_SEARCH 関数でベクトル インデックスが使用されました。

インデックス使用モードの値が UNUSED または PARTIALLY_USED の場合、「インデックスが使用されない理由」にクエリでベクトル インデックスが使用されなかった理由が示されます。

たとえば、bq show --format=prettyjson -j my_job_id から返された次の結果は、インデックスが使用されなかった理由が、VECTOR_SEARCH 関数で use_brute_force オプションが指定されているからであることが示されています。

"vectorSearchStatistics": {
  "indexUnusedReasons": [
    {
      "baseTable": {
        "datasetId": "my_dataset",
        "projectId": "my_project",
        "tableId": "my_table"
      },
      "code": "INDEX_SUPPRESSED_BY_FUNCTION_OPTION",
      "message": "No vector index was used for the base table `my_project:my_dataset.my_table` because use_brute_force option has been specified."
    }
  ],
  "indexUsageMode": "UNUSED"
}

インデックス管理オプション

インデックスを作成して BigQuery に維持させるには、次の 2 つの方法があります。

  • デフォルトの共有スロットプールを使用する: インデックスが付く予定のデータが組織ごとの上限を下回っている場合は、インデックス管理用に無料の共有スロットプールを使用できます。
  • 独自の予約を使用する: 大規模な本番環境ワークロードでより予測可能かつ一貫したインデックス付けを進めるため、インデックス管理用に独自の予約を使用できます。

共有スロットを使用する

インデックス専用の予約を使用するようプロジェクトをまだ構成していない場合、インデックス管理は次の制約に従い、無料の共有スロットプールで処理されます。

テーブルにデータを追加した結果としてインデックス付きテーブルの合計サイズが組織の上限を超えた場合、BigQuery はすべてのインデックス付きテーブルに対するインデックス管理を一時停止します。この場合、INFORMATION_SCHEMA.VECTOR_INDEXES ビューindex_status フィールドに PENDING DISABLEMENT が表示され、インデックスは削除対象のキューに入ります。インデックスの無効化が保留状態になっている間、そのインデックスは引き続き検索クエリで使用され、インデックス ストレージに対して料金が発生します。インデックスが削除されると、index_status フィールドにはインデックスが TEMPORARILY DISABLED として表示されます。この状態では、クエリはインデックスを使用せず、インデックス ストレージに対して料金は発生しません。この場合、IndexUnusedReason コードBASE_TABLE_TOO_LARGE です。

テーブルからデータを削除した結果、インデックス付きテーブルの合計サイズが組織ごとの上限を下回ると、すべてのインデックス付きテーブルのインデックス管理が再開します。INFORMATION_SCHEMA.VECTOR_INDEXES ビューの index_status フィールドは ACTIVE になり、クエリでインデックスを使用でき、インデックス ストレージに対して料金が発生します。

BigQuery は、共有プールの使用可能容量や確認されるインデックス処理スループットを保証することはありません。本番環境アプリケーションでは、インデックス処理に専用スロットを使用することをおすすめします。

独自の予約を使用する

デフォルトの共有スロットプールを使用する代わりに、必要に応じて、独自の予約を指定してテーブルにインデックスを付けることもできます。独自の予約を使用すると、作成、更新、バックグラウンド最適化などのインデックス管理ジョブのパフォーマンスが予測可能で一貫したものになります。

  • 予約でインデックス ジョブが実行されるときには、テーブルサイズの上限がありません。
  • 独自の予約を使用すると、インデックスを柔軟に管理できます。非常に大きなインデックスを作成する必要がある場合、またはインデックス付きテーブルを大幅に更新する必要がある場合には、より多くのスロットを一時的に割り当てに追加できます。

指定された予約を使用してプロジェクト内のテーブルにインデックスを付けるには、テーブルが配置されているリージョンで予約を作成します。次に、job_typeBACKGROUND に設定して、プロジェクトを予約に割り当てます。

SQL

CREATE ASSIGNMENT DDL ステートメントを使用します。

  1. Google Cloud コンソールで [BigQuery] ページに移動します。

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    CREATE ASSIGNMENT
      `ADMIN_PROJECT_ID.region-LOCATION.RESERVATION_NAME.ASSIGNMENT_ID`
    OPTIONS (
      assignee = 'projects/PROJECT_ID',
      job_type = 'BACKGROUND');
    

    次のように置き換えます。

    • ADMIN_PROJECT_ID: 予約リソースを所有する管理プロジェクトのプロジェクト ID
    • LOCATION: 予約のロケーション
    • RESERVATION_NAME: 予約の名前
    • ASSIGNMENT_ID: 割り当ての ID

      ID はプロジェクトとロケーションごとに一意でなければならず、先頭と末尾を英小文字または数字にする必要があり、英小文字、数字、ダッシュのみを使用できます。

    • PROJECT_ID: インデックスを付けるテーブルを含むプロジェクトの ID。このプロジェクトは予約に割り当てられます。

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリを実行するをご覧ください。

bq

bq mk コマンドを使用します。

bq mk \
    --project_id=ADMIN_PROJECT_ID \
    --location=LOCATION \
    --reservation_assignment \
    --reservation_id=RESERVATION_NAME \
    --assignee_id=PROJECT_ID \
    --job_type=BACKGROUND \
    --assignee_type=PROJECT

次のように置き換えます。

  • ADMIN_PROJECT_ID: 予約リソースを所有する管理プロジェクトのプロジェクト ID
  • LOCATION: 予約のロケーション
  • RESERVATION_NAME: 予約の名前
  • PROJECT_ID: この予約に割り当てられるプロジェクトの ID

インデックス ジョブの表示

単一のテーブルでインデックスが作成または更新されるたびに、新しいインデックス ジョブが作成されます。ジョブに関する情報を表示するには、INFORMATION_SCHEMA.JOBS* ビューをクエリします。クエリの WHERE 句で job_type IS NULL AND SEARCH(job_id, '`search_index`') を設定すると、インデックス ジョブをフィルタリングできます。次の例では、プロジェクト my_project 内の最新の 5 つのインデックス ジョブが一覧表示されます。

SELECT *
FROM
 region-us.INFORMATION_SCHEMA.JOBS
WHERE
  project_id  = 'my_project'
  AND job_type IS NULL
  AND SEARCH(job_id, '`search_index`')
ORDER BY
 creation_time DESC
LIMIT 5;

予約サイズの選択

予約に適切なスロット数を選択するには、インデックス管理ジョブが実行されるタイミング、使用されるスロット数、時間の経過に伴う使用状況の推移を考慮する必要があります。BigQuery は、次のようなときにインデックス管理ジョブをトリガーします。

  • テーブルにインデックスを作成したとき。
  • インデックス付きテーブルでデータが変更されたとき。
  • テーブルのスキーマが変更された影響として、どの列がインデックスに登録されるかが変化したとき。
  • インデックスのデータとメタデータが定期的に最適化または更新されるとき。

テーブルに対するインデックス管理ジョブに必要なスロット数は、次の要因に依存します。

  • テーブルのサイズ
  • テーブルへのデータ取り込みのレート
  • テーブルに適用される DML ステートメントのレート
  • インデックスを構築および維持するときに許容される遅延
  • インデックスの複雑さ(通常は、重複する語の数などのデータ属性によって決まります)
使用状況と進捗状況のモニタリング

インデックス管理ジョブを効率的に実行するのに必要なスロット数を評価する最良の方法は、スロットの使用状況をモニタリングし、それに応じて予約サイズを調整することです。次のクエリは、インデックス管理ジョブの日次スロット使用状況を生成します。リージョン us-west1 では過去 30 日間のみが含まれます。

SELECT
  TIMESTAMP_TRUNC(job.creation_time, DAY) AS usage_date,
  -- Aggregate total_slots_ms used for index-management jobs in a day and divide
  -- by the number of milliseconds in a day. This value is most accurate for
  -- days with consistent slot usage.
  SAFE_DIVIDE(SUM(job.total_slot_ms), (1000 * 60 * 60 * 24)) AS average_daily_slot_usage
FROM
  `region-us-west1`.INFORMATION_SCHEMA.JOBS job
WHERE
  project_id = 'my_project'
  AND job_type IS NULL
  AND SEARCH(job_id, '`search_index`')
GROUP BY
  usage_date
ORDER BY
  usage_date DESC
limit 30;

インデックス管理ジョブを実行するための十分なスロットがない場合、インデックスがテーブルと非同期状態になってインデックス ジョブが失敗することがあります。その場合、BigQuery はインデックスをまったくゼロの状態から再構築します。非同期インデックスを回避するには、データ取り込みと最適化によるインデックスの更新をサポートできるような十分なスロットがあることを確認してください。スロット使用状況のモニタリングの詳細については、管理リソースグラフをご覧ください。

ベクトル インデックスを削除する

ベクトル インデックスが不要になった場合や、インデックスを付けるテーブル上の列を変更する場合は、DROP VECTOR INDEX DDL ステートメントを使用して、そのテーブルのインデックスを削除できます。

例:

DROP VECTOR INDEX my_index ON my_dataset.indexed_table;

インデックスのあるテーブルが削除されると、そのインデックスは自動的に削除されます。

次のステップ