Cloud SQL for MySQL を使用してベクトル エンベディングを操作する

このページでは、Cloud SQL を操作してベクトル エンベディングを使用するアプリケーションを構築する方法について説明します。

Cloud SQL for MySQL は、ベクトル エンベディングの保存をサポートしています。その後、ベクトル検索インデックスを作成し、Cloud SQL に保存する残りのデータとともに、これらのベクトル エンベディングに対して類似検索を実行できます。

ベクトル エンベディングの保存

Cloud SQL for MySQL を使用してベクトル エンベディングを保存するには、テーブルにベクトル エンベディング列を作成します。特別なベクトル エンベディング列は、VARBINARY データ型にマッピングされます。テーブル内の他のリレーショナル データと同様に、既存のトランザクション保証に基づいてテーブル内のベクトル エンベディングにアクセスできます。ベクトル エンベディング列を持つテーブルは通常の InnoDB テーブルであるため、アトミック性、整合性、独立性、永続性(ACID)の特性に準拠しています。ベクトル検索インデックスのルックアップでのみ、ACID 特性は準拠されません。

1 つのテーブルに最大で 1 つのベクトル エンベディング列、1 つのベクトル検索インデックスを作成できます。同じ列に格納される各ベクトル エンベディングは、列を定義するときに指定したディメンションとまったく同じである必要があります。ベクトル エンベディングのディメンション数の上限は 16,000 です。十分なストレージとメモリが使用可能な場合は、異なるベクトル エンベディング列とベクトル検索インデックスを持つ別個のテーブルを同じインスタンスに作成できます。

テーブルに格納できるベクトル エンベディングの数にハードリミットはありませんが、ベクトル検索インデックスにはメモリが必要です。このため、テーブルに 1,000 万個を超えるベクトル エンベディングを格納しないことをおすすめします。

レプリケーションは、他の MySQL InnoDB 列の場合と同じように、ベクトル エンベディング列でも機能します。

Cloud SQL は、K 最近傍(KNN)検索クエリと近似最近傍(ANN)検索クエリの両方で類似検索をサポートしています。Cloud SQL インスタンスでは、どちらのタイプのベクトル検索も使用できます。ANN 検索にはベクトル検索インデックスを作成できます。

Cloud SQL は、KNN ベクトル検索(正確な最近傍検索)を使用するクエリをサポートしています。KNN ベクトル検索を実行すると、100% の再現率が得られます。KNN 検索は、ベクトル検索インデックスを作成せずに実行できます。KNN 検索は、テーブル スキャン アルゴリズムの実行に基づいています。

KNN 検索の場合、Cloud SQL は次のベクトル距離検索関数もサポートしています。

  • コサイン
  • ドット積
  • L2 二乗距離

ベクトル検索距離関数の使用方法については、ベクトル エンベディングの距離をクエリするをご覧ください。

Cloud SQL は、ベクトル検索インデックスの作成を通じて、ANN 検索の作成とクエリをサポートしています。ANN ベクトル検索インデックスを使用すると、100% の再現率ではなく、高速なパフォーマンスを重視して最適化できます。ANN 検索の場合、Cloud SQL は次のインデックス タイプをサポートしています。

  • BRUTE_FORCE: 行数が 10,000 未満のベーステーブルのデフォルトのベクトル検索インデックス タイプ。このタイプは、元のデータセットの小さなサブセット内の検索に最適です。インデックスで使用されるメモリは、データセットと同じサイズです。このインデックス タイプはディスクに保存されません。
  • TREE_SQ: 行数が 10,000 以上のベーステーブルのデフォルトのベクトル検索インデックス タイプ。このタイプは、最小限のメモリ(データセットのサイズの約 25%)を使用します。TREE_SQ インデックスはディスクに保存されます。
  • TREE_AH: 非対称ハッシュ検索タイプ アルゴリズムを提供するベクトル検索インデックス タイプ。Cloud SQL で実装されるこのインデックス タイプは、メモリ使用量向けに最適化されておらず、保存されません。

ベクトル検索インデックスを更新する

Cloud SQL for MySQL はベクトル検索インデックスをリアルタイムで更新します。ベーステーブルに対してデータ操作言語(DML)オペレーションを実行するトランザクションは、関連するベクトル検索インデックスにも変更を反映します。ベクトル検索インデックスの変更は、他のトランザクションすべてですぐに参照されます。つまり、分離レベルは READ_UNCOMMITTED です。

トランザクションをロールバックすると、ベクトル検索インデックスでも対応するロールバック変更が行われます。

ベクトル検索インデックスのレプリケーション

Cloud SQL for MySQL は、ベクトル検索インデックスをすべてのリードレプリカに複製します。レプリケーション フィルタと、カスケード レプリカへのベクトル検索インデックスの複製はサポートされていません。

ベクトル エンベディングをサポートするようにインスタンスを構成する

このセクションでは、ベクトル エンベディングの保存、インデックス登録、クエリをサポートするように Cloud SQL インスタンスを構成する方法について説明します。

Cloud SQL Enterprise エディションと Cloud SQL Enterprise Plus エディションの両方のインスタンスがベクトル エンベディングをサポートしています。

始める前に

  • インスタンスで Cloud SQL for MySQL MySQL バージョン 8.0.36.R20240401.03_00 以降を実行する必要があります。
  • インスタンスの合計ベクトル エンベディング数にメモリを割り当てるのに十分なディスク容量とメモリが、インスタンスには必要です。

ベクトル エンベディングのサポートを有効にする

ベクトル エンベディングのサポートを有効にするには、MySQL データベース フラグを構成する必要があります。

gcloud sql instances patch INSTANCE_NAME \
  --database-flags=FLAGS

INSTANCE_NAME は、ベクトル エンベディングのサポートを有効にするインスタンスの名前に置き換えます。

FLAGS で、インスタンスに次の MySQL フラグを構成します。

  • cloudsql_vector: このフラグを on に設定すると、ベクトル エンベディングの保存と検索のサポートが有効になります。インスタンスに新しいベクトル エンベディング列とベクトル検索インデックスを作成できます。
  • cloudsql_vector_max_mem_size: 省略可。インスタンスのすべてのベクトル検索インデックスの最大メモリ割り当てをバイト単位で指定します。このフラグを指定しない場合、デフォルトのメモリ割り当ては 1 GB です。これは最小メモリ割り当てです。指定する量の計算方法については、ベクトル検索インデックスのメモリ割り当てを構成するをご覧ください。

    この専用メモリは、innodb_buffer_pool_size に割り当てられたメモリから取得されます。使用可能なバッファプールは、同じ量だけ減少します。このフラグに許可される最大値は、総 innodb_buffer_pool_size50% です。

    innodb_buffer_pool_size の 50% を超える値を指定すると、Cloud SQL は値を使用可能なサイズの 50% に減らし、インスタンスの警告メッセージを記録します。

フラグを構成すると、コマンドは次のようになります。

gcloud sql instances patch my-instance \
  --database-flags=cloudsql_vector=on,cloudsql_vector_max_mem_size=4294967296

Cloud SQL for MySQL でベクトル エンベディングのサポートを構成するフラグは静的フラグです。フラグを使用してインスタンスを更新すると、構成の変更を有効にするためにインスタンスが自動的に再起動します。

MySQL のデータベース フラグを構成する方法については、データベース フラグを構成するをご覧ください。

ベクトル エンベディングのサポートを無効にする

ベクトル エンベディングのサポートを無効にするには、cloudsql_vector フラグを off に設定します。

次に例を示します。

gcloud sql instances patch INSTANCE_NAME \
  --database-flags=cloudsql_vector=off

INSTANCE_NAME は、ベクトル エンベディングのサポートを無効にするインスタンスの名前に置き換えます。

cloudsql_vectoroff に設定すると、新しいベクトル エンベディング列とベクトル検索インデックスを作成できなくなります。この静的フラグを構成すると、構成変更が有効になるようにインスタンスが自動的に再起動します。

インスタンスの再起動後、Cloud SQL for MySQL は次の処理を行います。

  • 永続ディスクから保持している TREE_SQ ベクトル検索インデックスをすべて削除します。
  • 構築されたベクトル検索インデックスのデータ ディクショナリ テーブルのエントリを保持します。ただし、Cloud SQL for MySQL はインデックスを再構築しません。これらのインデックスに対する検索クエリはエラーを返します。
  • ベクトル エンベディングをベーステーブルに格納したままにします。ベクトル エンベディングには引き続きアクセスできます。

後でインスタンスの cloudsql_vector フラグを再度有効にすると、インスタンスの再起動時に、Cloud SQL はデータ ディクショナリ テーブルのエントリに基づいてインデックスの再構築を試みます。

ベクトル検索インデックスのメモリ割り当てを構成する

Cloud SQL は、メモリ内にベクトル検索インデックスを構築して維持します。TREE_SQ インデックス タイプは、クリーン シャットダウン時に保持され、インスタンスの再起動後に再読み込みされます。実行時には、すべてのベクトル検索インデックスをメモリ内に保持する必要があります。

Cloud SQL で、すべてのベクトル検索インデックスをメモリ内に保持するのに十分なメモリを確保するには、cloudsql_vector_max_mem_size データベース フラグを使用して Cloud SQL インスタンスを構成します。cloudsql_vector_max_mem_size は、Cloud SQL インスタンスがベクトル検索インデックスに割り当てるメモリ量を制御します。フラグの値を構成する際は、次の点に注意してください。

  • デフォルト値と最小値は 1 GB です。上限はバッファプール サイズの 50% です。
  • このフラグを設定すると、構成の変更を有効にするためにインスタンスが自動的に再起動します。
  • インスタンスで構成されたメモリがすべて使用されている場合、ベクトル検索インデックスを作成または変更することはできません。

インスタンスのベクトル検索インデックスに割り当てるメモリを更新するには、cloudsql_vector_max_mem_size フラグの値を変更します。

gcloud sql instances patch INSTANCE_NAME \
  --database-flags= cloudsql_vector_max_mem_size=NEW_MEMORY_VALUE

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

  • INSTANCE_NAME: メモリ割り当てを変更するインスタンスの名前。
  • NEW_MEMORY_VALUE: ベクトル検索インデックスの更新されたメモリ割り当て(バイト単位)

この変更で、インスタンスが自動的に再起動されて変更が有効になります。

必要なメモリを計算する

インデックスに必要なメモリ量は、インデックス タイプ、ベクトル エンベディングの数、エンベディングの次元によって異なります。考慮すべきメモリ要件は 2 つあります。

  • 構築時のメモリ: インデックスの構築時に必要なメモリ
  • インデックス メモリ: インデックスの構築後にインデックスが占有するメモリ

特定のインデックスで、データセットのサイズは、メモリ内のすべてのベクトル エンベディングを読み取るために必要なメモリです。各ディメンションが 4 バイトのメモリを使用する浮動小数点数で表されるため、dataset_size は次のように決定されます。

dataset_size = <num_embeddings> * (4 * <dimensions>)

たとえば、ディメンション数が 768 のエンベディングが 100 万個ある場合、dataset_size は 3 GB になります。

前述の例で、さまざまなインデックス タイプのメモリ要件は次のとおりです。

インデックス タイプ 構築時のメモリ インデックス メモリ
TREE_SQ 4 GB 1 GB
TREE_AH 3.5 GB 3.5 GB
BRUTE_FORCE 3 GB 3 GB

TREE_SQ ベクトル検索インデックスを使用している場合は、実行時の永続性に必要なメモリも考慮する必要があります。構成の合計メモリ量に、アクティブな最大の TREE_SQ ベクトル検索インデックスで使用されるインデックス メモリの量を加算します。

ベクトル エンベディングが格納されているベーステーブルで DML オペレーションが行われると、ベクトル検索インデックスがリアルタイムに更新されます。これらの更新により、インデックスのメモリ使用量が変更され、DML オペレーションに応じて減少または増加します。インデックスのメモリ使用量は、information_schema.innodb_vector_indexes テーブルをクエリしてモニタリングできます。ベクトル検索インデックスのサイズのモニタリングについては、ベクトル検索インデックスをモニタリングするをご覧ください。

リードレプリカの構成

インスタンスがメンテナンス バージョンとフラグ有効化の条件を満たしている場合、Cloud SQL はリードレプリカのベクトル エンベディングを完全にサポートします。

ベクトル エンベディングのサポートが有効になっているプライマリ インスタンスからレプリカを作成すると、リードレプリカはベクトル エンベディングのサポートの設定をプライマリ インスタンスから継承します。既存のリードレプリカ インスタンスでは、ベクトル エンベディングのサポートを個別に有効にする必要があります。

ベクトル検索インデックスの作成と維持で、レプリケーション ラグへの影響は通常の MySQL インデックスと同様です。

ベクトル検索インデックスは、カスケード レプリカではサポートされていません。

例: シンプルな ANN ベクトル検索インデックスとクエリ

次のチュートリアルの例では、Cloud SQL で ANN ベースのベクトル検索インデックスとクエリを作成する手順を示します。

  1. ベクトル エンベディングを生成します。ベクトル エンベディングの作成は手動で行うことも、任意のテキスト エンベディング API を使用することもできます。Vertex AI を使用する例については、行データに基づいてベクトル エンベディングを生成するをご覧ください。

  2. Cloud SQL for MySQL で、3 つのディメンションを持つベクトル エンベディング列を含むテーブルを作成します。

    CREATE TABLE books (
    id   INTEGER PRIMARY KEY AUTO_INCREMENT,
    title VARCHAR(60),
    embedding VECTOR(3) USING VARBINARY
    );
    
  3. ベクトル エンベディングを 1 つ、その列に挿入します。

    INSERT INTO books VALUES (
    1,
    'book title',
     string_to_vector('[1,2,3]')
    );
    
  4. 変更を commit します。

    commit;
    
  5. ベクトル検索インデックスを作成します。TREE_SQ インデックスまたは TREE_AH インデックスを作成する場合は、テーブルに 1,000 行以上が必要です。

    CALL mysql.create_vector_index('vectorIndex',
                                   'dbname.books',
                                   'embedding',
                                   'index_type=BRUTE_FORCE, distance_measure=L2_SQUARED'
                                   );
    
  6. 最近傍を取得します。

    SELECT title FROM books
    WHERE
    NEAREST(embedding) TO (string_to_vector('[1,2,3]'));
    

行データに基づいてベクトル エンベディングを生成する

Vertex AIOpenAI などのテキスト エンベディング API を使用して、特定の行のデータのベクトル エンベディングを生成できます。Cloud SQL のベクトル エンベディングでは、任意のテキスト エンベディング API を使用できます。ただし、クエリ文字列ベクトルの生成に、同じテキスト エンベディング API を使用する必要があります。ソースデータとクエリのベクトル化で異なる API を組み合わせることはできません。

たとえば、ベクトル エンベディングを Vertex AI から生成できます。

from vertexai.language_models import TextEmbeddingModel

def text_embedding() -> list:
    """Text embedding with a Large Language Model."""
    model = TextEmbeddingModel.from_pretrained("textembedding-gecko@001")
    embeddings = model.get_embeddings(["What is life?"])
    for embedding in embeddings:
        vector = embedding.values
        print(f"Length of Embedding Vector: {len(vector)}")
    return vector

if __name__ == "__main__":
    text_embedding()

ベクトル エンベディングを保存する

このセクションでは、Cloud SQL でベクトル エンベディングを保存するステートメントの例を示します。

ベクトル エンベディング列を含む新しいテーブルを作成する

CREATE TABLE books (
  id INTEGER PRIMARY KEY AUTO_INCREMENT,
  title VARCHAR(60),
  embedding VECTOR(3) USING VARBINARY
  );

既存のテーブルにベクトル エンベディング列を追加する

ALTER TABLE books
ADD COLUMN embedding
VECTOR(3) USING VARBINARY;

ベクトル エンベディングを挿入する

INSERT INTO books (
  title,
  embedding
  ) VALUES (
    'book title',
    string_to_vector('[1,2,3]')
);

複数のベクトル エンベディングを挿入する

INSERT INTO books (
  title,
  embedding
  ) VALUES (
    'book title',
    string_to_vector('[1,2,3]')),
     ('book title', string_to_vector('[4,5,6]')
);

ベクトル エンベディングの Upsert

INSERT INTO books (
  id,
  title,
  embedding
  ) VALUES (
    1,
    'book title',
     string_to_vector('[1,2,3]')
     )
ON DUPLICATE KEY UPDATE embedding = string_to_vector('[1,2,3]');

ベクトル エンベディングを更新する

UPDATE books
SET embedding = string_to_vector('[1,2,3]')
WHERE id = 1;

ベクトル エンベディングを削除する

DELETE FROM books
WHERE embedding = string_to_vector('[1,2,3]');

ベクトル検索インデックスを操作する

デフォルトでは、100% の再現率を保証する正確な最近傍検索を実行できます。インデックスを追加して ANN 検索を使用することもできます。この場合、速度は向上しますが、再現率が低下します。通常のインデックスとは違い、近似インデックスを追加すると異なるクエリ結果が返されます。

推奨事項

このセクションでは、ベクトル検索インデックスの操作に関するベスト プラクティスについて説明します。ワークロードはそれぞれ異なるため、必要に応じて調整する必要があります。

  • ベクトル検索インデックスを作成する前に、テーブルにデータを読み込む必要があります。ベーステーブルには 1,000 行以上が必要です。これらの要件は、TREE_SQTREE_AH の検索インデックス タイプにのみ適用されます。利用可能なデータポイントが多いほど、インデックスのパーティショニングとトレーニングが向上します。
  • インデックスのメモリ使用量をモニタリングします。インスタンスのメモリが不足すると、インデックスを作成または構築できなくなります。既存のインデックスの場合、しきい値に達すると、Cloud SQL は MySQL エラーログに定期的に警告を書き込みます。メモリ使用量は information_schema.innodb_vector_indexes テーブルで確認できます。
  • 基になるベーステーブルに DML の大きな変更が加えられた場合は、ベクトル検索インデックスを再構築します。構築時のインデックスの初期サイズと現在のインデックスのサイズを取得するには、information_schema.innodb_vector_indexes テーブルに対してクエリを実行します。
  • 一般に、パーティション数を内部で計算するようにしておいても問題ありません。パーティション数を指定するユースケースがある場合は、パーティションごとに少なくとも 100 個のデータポイントを用意する必要があります。

ベクトル検索インデックスのオペレーション中の読み取り専用ベーステーブル

ベクトル検索インデックスの 3 つのオペレーション(作成、変更、削除)のすべてで、その最中にベーステーブルは読み取り専用モードになります。これらのオペレーション中は、ベーステーブルに対する DML は許可されません。

永続性、シャットダウン、メンテナンスへの影響

インスタンスのクリーン シャットダウン時に、TREE_SQ タイプを使用するベクトル検索インデックスのみがディスクに保持されます。TREE_AH タイプおよび BRUTE_FORCE タイプを使用するベクトル検索インデックスは、インメモリのみです。

インスタンスのクリーン シャットダウン後、Cloud SQL はインスタンスの再起動時にベクトル検索インデックスを再読み込みします。しかし、クラッシュ後またはクリーンでないシャットダウンの後には、Cloud SQL はベクトル検索インデックスを再構築する必要があります。たとえば、インスタンスがクラッシュし、バックアップと復元、ポイントインタイム リカバリ(PITR)、または高可用性(HA)フェイルオーバーから復旧すると、Cloud SQL はベクトル検索インデックスを再構築します。これらのイベントでは、次のように処理されます。

  • 再構築はバックグラウンドで自動的に行われます。
  • 再構築中、ベーステーブルは読み取り専用モードになります。
  • 自動再構築で特定のタイムアウト期間内にテーブルのロックを取得できない場合、再構築は失敗します。そのような場合は、インデックスを手動で再構築する必要があります。

インデックスの再構築に要する時間のために、シャットダウンに要する時間が長くなることがあり、さらにインスタンスで必要なメンテナンスと更新に要する時間も長くなることがあります。

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

ベクトル検索インデックスを作成するためのステートメントは、次の構文を使用します。

CALL mysql.create_vector_index('INDEX_NAME',
                                'DB_NAME.TABLE_NAME',
                                'COLUMN_NAME',
                                'PARAMETERS'
                              );

次に例を示します。

CALL mysql.create_vector_index('vectorIndex',
                                'db.books',
                                'embedding',
                                'index_type=TREE_SQ, distance_measure=l2_squared'
                               );

指定するインデックス名は、データベース内で一意である必要があります。

ベクトル検索インデックスのパラメータ

検索インデックス作成(および検索インデックス変更)関数は、カンマ区切りの Key-Value ペアで指定できる複数のパラメータをサポートしています。検索インデックス作成関数のパラメータはすべて省略可能です。空の文字列または NULL を指定すると、インデックスのデフォルトのパラメータ値が構成されます。

  • distance_measure: サポートされている値は L2_SQUAREDCOSINEDOT_PRODUCT です。デフォルトは L2_SQUARED です。
  • num_neighbors: ANN クエリの際にデフォルトで返される近傍の数。検索クエリの実行時にこのパラメータをオーバーライドできます。デフォルトは 10 です。
  • index_type: 構築するインデックスのタイプを指定します。有効な値は BRUTE_FORCETREE_SQTREE_AH です。

    • BRUTE_FORCE は、行数が 10,000 未満のテーブルのデフォルトです。
    • TREE_SQ は、行数が 10,000 以上のテーブルのデフォルトです。

    TREE_AH または TREE_SQ インデックス タイプを指定するには、ベーステーブルのサイズが 1,000 行を超えている必要があります。

  • num_parititions: 構築する K 平均法クラスタの数を指定します。このパラメータは、index_type を構成している場合にのみ使用できます。このオプションは BRUTE_FORCE には適用されません。TREE_SQ または TREE_AH インデックス タイプを指定する場合、ベーステーブルのサイズは num_partitions × 100 以上である必要があります。

ベクトル検索インデックスを変更する

CALL mysql.alter_vector_index('DB_NAME.INDEX_NAME', 'PARAMETERS');

alter_vector_index 関数は、ベクトル検索インデックスを再構築するために明示的に使用されます。この関数を使用するには、インデックスがすでに存在している必要があります。インデックスの再構築は、次のようなユースケースで必要になることがあります。

  • 別のオプションを使用してインデックスを再構築する場合。たとえば、別のインデックス タイプや距離測定の使用が必要になることがあります。
  • ベーステーブルに大きな DML の変更が加えられたため、インデックスを再構築する場合。たとえば、ベーステーブルの現在のデータに基づいてベクトル検索インデックスの再トレーニングが必要になることがあります。

インデックスの再構築に使用されるパラメータはすべて、インデックスの作成に使用できるパラメータと同じであり、省略も可能です。インデックスの再構築時に空の文字列または NULL を指定すると、インデックスの作成時に指定したパラメータに基づいてインデックスが再構築されます。インデックスの作成時にパラメータが指定されていない場合は、デフォルトのパラメータ値が使用されます。

変更オペレーション中に、既存のベクトル検索インデックスは使用可能です。インデックスに対する検索クエリは依然として実行できます。

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

ベクトル検索インデックスのあるテーブルに対して DDL オペレーションを実行できません。テーブルに対して DDL オペレーションを実行する前に、ベクトル検索インデックスを削除する必要があります。

CALL mysql.drop_vector_index('DB_NAME.INDEX_NAME');

ベクトル エンベディングのクエリ

このセクションでは、ベクトル エンベディングをクエリするさまざまな方法の例を示します。

ベクトル エンベディングを表示する

SELECT vector_to_string(embedding) FROM books;

ベクトル エンベディングの正確な近傍検索を取得する

SELECT id,cosine_distance(embedding,
   string_to_vector('[1,2,3]')) dist
FROM books
ORDER BY dist
LIMIT 10;

ベクトル エンベディングの近似近傍検索を取得する

SELECT title FROM books
WHERE
NEAREST(embedding) TO (string_to_vector('[1,2,3]'), 'num_neighbors=10');

ANN 検索の実行では、2 つのパラメータがサポートされます。どちらも省略可能です。

  • num_partitions: ANN ベクトル検索でプローブするパーティション数を指定します。パーティション数を指定しない場合、テーブルのサイズ、ベクトル検索インデックス内のパーティションの数、その他の要因に基づいて生成された値が使用されます。
  • num_neighbors: 返される近傍の数を指定します。この値は、ベクトル検索インデックスの作成時に設定された値をオーバーライドします。

ベクトル エンベディングをフィルタする

追加の列を述語として使用して、ベクトル エンベディングのクエリ結果のフィルタリングを微調整します。たとえば、printyear 列を追加すると、特定の年をフィルタとしてクエリに追加できます。

SELECT title FROM books
WHERE
NEAREST(embedding) TO (string_to_vector('[1,2,3]'))
AND printyear > 1991;

ベクトル エンベディングの距離をクエリする

このセクションでは、KNN 検索で使用できるベクトル距離関数の例を示します。

コサイン距離を取得する

SELECT cosine_distance(embedding, string_to_vector('[3,1,2]'))
AS distance FROM books WHERE id=10;

ドット積距離を取得する

SELECT dot_product(embedding, string_to_vector('[3,1,2]'))
AS distance FROM books WHERE id=10;

L2 二乗距離を取得する

SELECT l2_squared_distance(embedding, string_to_vector('[3,1,2]'))
AS distance FROM books WHERE id=10;

一定の距離内の行を取得する

SELECT * FROM books
WHERE l2_squared_distance(embedding, string_to_vector('[1,2,3]')) < 10;

ORDER BYLIMIT を組み合わせることができます。

SELECT id, vector_to_string(embedding),
       l2_squared_distance(embedding, string_to_vector('[1,2,3]')) dist
FROM books ORDER BY dist LIMIT 10;

ベクトル検索インデックスをモニタリングする

インスタンスのすべてのベクトル検索インデックスに関するリアルタイム情報を取得するには、information_schema.innodb_vector_indexes テーブルを使用します。

テーブルを表示するには、次のコマンドを実行します。

SELECT * FROM information_schema.innodb_vector_indexes;

出力例は次のようになります。

*************************** 1. row ***************************
       INDEX_NAME: test.t4_index
       TABLE_NAME: test.t4_bf
       INDEX_TYPE: BRUTE_FORCE
     DIST_MEASURE: SquaredL2Distance
           STATUS: Ready
            STATE: INDEX_READY_TO_USE
       PARTITIONS: 0
SEARCH_PARTITIONS: 0
     INITIAL_SIZE: 40000
     CURRENT_SIZE: 40000
          QUERIES: 0
        MUTATIONS: 0
     INDEX_MEMORY: 160000
   DATASET_MEMORY: 0

information_schema.innodb_vector_indexes テーブルには次の情報が表示されます。

  • 生成される可能性のあるオプション。つまり、num_partitions またはクエリでプローブするパーティション数。
  • STATE 列と STATUS 列には、インデックスの現在の状態が表示されます。構築フェーズでは、ステータス列にベクトル検索インデックスが構築フェーズでどの程度進行しているかの情報が表示されます。
  • INITIAL_SIZE 列には、インデックス作成時のテーブルサイズが表示されます。このサイズを CURRENT_SIZE と比較すると、ベーステーブルに対する DML によってインデックスが作成時からどれだけ変化したかがわかります。
  • QUERIES 列と MUTATIONS 列には、インデックスの使用状況に関するリアルタイムの分析情報が表示されます。
  • INDEX_MEMORY 列と DATASET_MEMORY 列には、インデックスのメモリ消費量に関する情報が表示されます。INDEX_MEMORY

    はインデックスによって消費されるメモリ量、DATASET_MEMORY は構築時に追加で消費されるメモリ量を示します。

インスタンスで作成された検索ベクトル インデックスのリストを取得するには、mysql.vector_indexes データ ディクショナリ テーブルを表示します。

テーブルを表示するには、次のコマンドを実行します。

SELECT * FROM mysql.vector_indexes;

出力例:

*************************** 1. row ***************************
   index_name: test.index1
   table_name: test.t1
  column_name: j
index_options: index_type=BRUTE_FORCE, distance_measure=L2_SQUARED
       status: ACTIVE
  create_time: 2024-04-08 22:46:21
  update_time: 2024-04-08 22:46:21
1 row in set (0.00 sec)

制限事項

  1. 1 つのテーブルには、ベクトル エンベディング列を 1 つのみ指定できます。
  2. 1 つのテーブルには、ベクトル検索インデックスを 1 つのみ作成できます。
  3. ベクトル エンベディングは最大 16,000 個のディメンションを持つことができます。
  4. ベクトル エンベディング列を含むテーブルの InnoDB テーブルレベルのパーティショニングはサポートされていません。
  5. クリーン シャットダウンからインスタンスが再起動すると、Cloud SQL はベクトル検索インデックスを自動的に再構築します。
    1. ベクトル検索インデックスを再構築している間、ベーステーブルは読み取り専用になります。
    2. Cloud SQL が指定された時間内にテーブルのロックを取得できない場合、インデックスの自動再構築が失敗する可能性があります。
    3. インデックスの自動再構築が失敗した場合は、インデックスを手動で再構築する必要があります。
  6. ベクトル エンベディング列を追加するには、テーブルに主キーが必要です。Cloud SQL は、BITBINARYVARBINARYJSONBLOBTEXT、または空間データ型の主キーをサポートしていません。複合主キーには、これらの型を含めることはできません。
  7. テーブルにベクトル検索インデックスが存在する場合、DDL オペレーションは許可されません。ベーステーブルで DDL オペレーションを実行する前に、ベクトル検索インデックスを削除する必要があります。
  8. InnoDB 以外のテーブルや、一時テーブルでは、ベクトル エンベディングはサポートされていません。
  9. ベクトル エンベディング列は、生成列にすることはできません。
  10. NEAREST..TO 述語は、AND または OR を使用して、他の「スカラー」述語と組み合わせることができます。テーブルのスカラー述語は、ベクトル述語が適用された後に評価されます。
  11. NEAREST..TO 述語は、SELECT ステートメントでのみサポートされています。他の DML ステートメントでは、NEAREST..TO はサポートされていません。
  12. サブクエリは NEAREST..TO でサポートされていません。ベクトル検索インデックスが存在する場合、ベーステーブルの主キーに制約を追加することはできません。
  13. 事前フィルタリングは、ORDER BYLIMIT とともに使用し、距離関数を通してのみ実現可能です。

    たとえば、次のテーブルを作成したとします。

    CREATE TABLE books
    (
    bookid          INT PRIMARY KEY,
    title           VARCHAR(1000),
    author          VARCHAR(100),
    printyear       int,
    country         VARCHAR(100),
    bvector         VECTOR(1536) USING VARBINARY
    //bvector is embedding vector of book's plot,genre,reviews etc
    );
    

    そして、次のクエリを使用して事前フィルタリングを行います。

    //select query to obtain books by specific author and having similar plot-genre-reviews
    SELECT bookid, title, author,l2_squared_distance(bvector, qvector) dist
    FROM books where author='cloudsql' ORDER BY dist LIMIT 10
    

    事後フィルタリングは、NEAREST..TO 関数と距離関数でサポートされています。

トラブルシューティング

クラッシュが発生した場合、インデックスは自動的に再構築されます。再構築の進行中は、次の 2 つの制限があります。

  1. インデックスの作成中、ベーステーブルは読み取り専用モードになります。
  2. インデックスの再作成中は、既存のインデックスに対する ANN クエリは失敗します。

次のステップ