ベクトル エンベディングを使用した検索とフィルタ

このページでは、ベクトル エンベディングをクエリするさまざまな方法について説明します。ANN と KNN の類似検索の概要については、ベクトル検索をご覧ください。

近似最近傍(ANN)を検索する

ANN 検索を実行するには、SELECT 句と ORDER BY 句で approx_distance 関数を使用します。ANN 検索では LIMIT 句を使用する必要があります。approx_distanceSELECT リストに追加することで、距離値を取得することもできます。

ANN クエリには次の構文を使用します。

# Ordering by distance
SELECT title
FROM books
ORDER BY approx_distance(embedding, string_to_vector('[1,2,3]'), 'distance_measure=l2_squared')
LIMIT 4;

# Selecting the distance value
SELECT
  approx_distance(
    embedding_name,
    string_to_vector('[1,2,3]'),
    'distance_measure=cosine,num_leaves_to_search=3')
    dist
FROM table
ORDER BY dist
LIMIT limit_value;

approx_distance 関数では、次のオプションを使用します。

  • embedding: ベーステーブルのベクトル エンベディング列名を使用します。
  • string_to_vector または vector_to_string: ベクトルを文字列に変換し、文字列をベクトルに変換して、ベクトルを人が読める形式にします。
  • distance_measure: ベクトル類似検索に使用する距離測定を指定します。この値は、インデックスの作成時に distance_measure パラメータで設定した値と一致する必要があります。このパラメータは必須です。このパラメータで指定できる値は次のとおりです。
    • COSINE
    • L2_SQUARED
    • DOT_PRODUCT
  • num_leaves_to_search: 省略可。ANN ベクトル類似検索でプローブするリーフの数を指定します。リーフの数を指定しない場合、Cloud SQL はテーブルのサイズ、ベクトル インデックス内のリーフの数、その他の要因に基づいて生成された値を使用します。この値は information_schema.innodb_vector_indexes で確認できます。特定のワークロードの検索品質とパフォーマンスの最適なバランスを実現するために、num_leaves_to_search をファインチューニングすることをおすすめします。値を大きくするとパフォーマンスに影響しますが、再現率は向上します。

次の例は、approx_distance を使用して、l2_squared 距離測定で Top-K の最も近い行を見つけ、結果を距離で並べ替える方法を示しています。

# Ordering by distance
SELECT title
FROM books
ORDER BY approx_distance(embedding, string_to_vector('[1,2,3]'),
                         'distance_measure=l2_squared')
LIMIT 4;

# Selecting the distance value
SELECT
    approx_distance
        (embedding, string_to_vector('[1,2,3]'),
         'distance_measure=l2_squared') dist
FROM table
ORDER BY dist
LIMIT 4;

approx_distance クエリの結果をフィルタする

approx_distance 関数では、ベクトル以外の述語を使用してクエリ結果をフィルタする WHERE 条件を指定して、事後フィルタリングを実行できます。approx_distance 関数はフィルタの適用前に評価されるため、返される結果の数は非決定的です。

たとえば、次のクエリの場合:

SELECT id FROM products WHERE price < 100
ORDER BY approx_distance(embedding, @query_vector,'distance_measure=cosine')
LIMIT 11;

approx_distance 関数は、価格に関係なく、クエリベクトルの 11 個の最近傍を返します。事後フィルタリングでは、価格が 100 未満の商品が選択されます。すべての最近傍の価格が 100 未満であるために、クエリの結果が 11 件になる可能性があります。または、最近傍のいずれも価格が 100 未満でない場合、返される行は 0 行になります。

WHERE 条件のフィルタの選択性が高いと予想される場合は、完全一致検索(KNN)を使用すると、十分な数の行が返される可能性があります。

もう 1 つの方法は、反復フィルタリングを使用して、ANN 検索インデックスをより多くスキャンすることです。

反復フィルタリングを使用して ANN 検索結果を増やす

ANN 検索クエリの WHERE 句の選択的フィルタで、LIMIT 句で指定された結果の数よりも少ない結果が生成される場合は、反復フィルタリングを使用できます。

たとえば、次のクエリで反復フィルタリングを有効にすると、クエリはフィルタリングされた結果の最初のセットを除いたベクトル インデックスをより多くスキャンします。

EXPLAIN FORMAT=TREE
SELECT * FROM t1 WHERE next_id BETWEEN 15 AND 100
ORDER BY approx_distance(embedding, string_to_vector('[1,2,3]'), 'distance_measure=l2_squared')
LIMIT 10;

EXPLAIN
-> Limit: 10 row(s)  (rows=10)
   -> Vector index loop with iterative filtering
      -> Vector index scan on t1
      -> Filter: (t1.next_id between 15 and 100)
         -> Single-row index lookup on t1 using PRIMARY (id=t1.id)

構成された最大値(cloudsql_vector_iterative_filtering_max_neighbors)に達するまで、検索ベクトル インデックスから近傍を繰り返し取得します。フィルタに一致したものは LIMIT にカウントされ、追加のベクトル インデックス スキャンから削除されます。

反復フィルタリングを有効にする

デフォルトでは、すべてのセッションと Cloud SQL インスタンスで反復フィルタリングが無効になっています。

既存のセッションで反復フィルタリングを有効にするには、次の SQL ステートメントを使用します。

SET SESSION cloudsql_vector_iterative_filtering=on;

インスタンスでフラグを設定して、インスタンスに接続するすべてのクライアント セッションで反復フィルタリングをグローバルに有効にすることもできます。インスタンスのフラグを設定するには、データベース フラグを設定するをご覧ください。

セッション レベルまたはグローバル レベルでシステム変数を設定する方法については、MySQL ドキュメントのシステム変数の使用をご覧ください。

反復フィルタリングを調整する

反復フィルタリングが有効になっている ANN 検索クエリで返される最近傍の数を制御するには、cloudsql_vector_iterative_filtering_max_neighbors セッションまたはグローバル システム変数を使用します。この構成を使用すると、リクエストされる最近傍の数を増やすことができます。ただし、メモリに保存される結果が多すぎないように、この変数の最大値は 1000 です。

セッションでこの変数を設定するには、次の SQL ステートメントを使用します。

SET cloudsql_vector_iterative_filtering_max_neighbors=600;

デフォルト値は 500、最小値は 10 です。

制限事項

反復フィルタリングの使用には、次の制限があります。

  • 保証ではない: 反復フィルタリングを使用すると、Cloud SQL は LIMIT 句で指定された結果の数を検索しようとしますが、その数が検出されることは保証されません。この現象は、LIMIT が満たされる前に近傍の最大数(cloudsql_vector_iterative_filtering_max_neighbors)に達した場合や、テーブル内のフィルタに一致する行が十分にない場合に発生することがあります。

  • 複雑なクエリ: フィルタ述語がベーステーブルのアクセスパスにプッシュダウンされた場合にのみ、反復フィルタリングが機能します。一時テーブルのフィルタ(HAVING 句を使用するテーブルなど)ではサポートされていません。サブクエリでは、サブクエリ内のベーステーブルのフィルタのみが反復フィルタリングの対象となります。

ANN 検索のフォールバック ステータスを確認する

ANN 検索が KNN 検索にフォールバックする場合があります。次に例を示します。

  • ベーステーブルにベクトル インデックスがない。
  • ベーステーブルにベクトル インデックスがあるが、approx_distance 検索オプションの distance_measure パラメータとは異なる距離測定を使用している。
  • ベクトル インデックスが破損しているか、現在のトランザクションに表示されない。
  • 指定された LIMIT が 10,000 より大きい。
  • LIMIT が指定されていない。
  • 現在のクエリに、同じベーステーブルに対する複数の approx_distance 呼び出しが含まれている。
  • オプティマイザーで、KNN を使用するほうが効率的であると計算されている。

これらのケースではすべて、完全一致検索が実行されたこととその理由を示す警告がクライアントに push されます。

mysql クライアントで次のコマンドを使用して、フォールバック ステータスを表示します。

SHOW global status LIKE '%cloudsql_vector_knn_fallback%';

ANN を使用するつもりが KNN にフォールバックすると、クエリの実行速度が低下する可能性があります。フォールバックしている理由を特定し、代わりに ANN が使用されるように変更するかどうかを評価する必要があります。

例: ベクトル インデックスを作成し、ANN クエリを実行する

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

  1. ベクトル エンベディングを生成します。ベクトル エンベディングの作成は手動で行うことも、任意のテキスト エンベディング API を使用することもできます。Vertex AI を使用する例については、行データに基づいてベクトル エンベディングを生成するをご覧ください。
  2. Cloud SQL で、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. L2_squared 関数を使用してベクトル インデックスを作成し、距離を測定します。

    CREATE
      VECTOR INDEX vectorIndex
    ON dbname.books(embeddings)
    USING SCANN QUANTIZER = SQ8 DISTANCE_MEASURE = l2_squared;
    
  6. 検索結果が 4 件の LIMIT を指定して ANN 検索を実行するには、次の構文を使用します。

    SELECT title
    FROM books
    ORDER BY approx_distance(embedding, string_to_vector('[1,2,3]'), 'distance_measure=l2_squared')
    LIMIT 4;
    
    SELECT approx_distance(embedding, string_to_vector('[1,2,3]'), 'distance_measure=cosine') dist
    FROM books
    ORDER BY dist
    LIMIT 4;
    

K 最近傍(KNN)を検索する

K 最近傍検索を実行するには、SELECT ステートメントで距離測定オプションとベクトル変換関数(string_to_vector または vector_to_string)を指定して vector_distance 関数を使用します。次の構文を使用します。

SELECT vector_distance(string_to_vector('[1,2,3]'),
                      string_to_vector('[1,2,3]'),
                      'Distance_Measure=dot_product');

値 [1,2,3] は、データのエンベディング値に置き換えます。

次の例は、cosine_distance 関数と string_to_vector ベクトル変換関数を指定してこのクエリを使用する方法を示しています。

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

KNN クエリでコサイン距離を取得する

Cloud SQL の cosine_distance 関数を使用して、コサインで距離を計算します。

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

KNN クエリでドット積距離を取得する

Cloud SQL の dot_product 関数を使用して、ドット積で距離を計算します。

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

KNN クエリで L2 二乗距離を取得する

Cloud SQL の l2_squared_distance 関数を使用して、L2 二乗で距離を計算します。

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

次のステップ