次の方法で共有


DiskANN 拡張機能を有効にして使用する

DiskANN は、あらゆる規模で効率的なベクトル検索を行うためのスケーラブルな最近傍探索アルゴリズムです。 10 億ポイントのデータセットであっても、高い再現率、1 秒あたりの高いクエリ、低いクエリ待ち時間が提供されます。 これらの特性により、大量のデータを処理するための強力なツールになります。

DiskANN の詳細については、「DiskANN: Web スケールの検索のためのベクトル検索と推奨事項」を参照してください。

pg_diskann拡張機能では、効率的なベクター インデックス作成と検索に DiskANN を使用するためのサポートが追加されています。

pg_diskannを有効にする

Azure Database for PostgreSQL フレキシブル サーバー インスタンスで pg_diskann 拡張機能を使用するには、インスタンス レベルで 拡張機能を許可 する必要があります。 次に、拡張機能によって提供される機能を使用する各データベースに拡張機能を 作成 する必要があります。

pg_diskannには vector 拡張機能への依存関係があるため、同じデータベースに 拡張機能を許可してvectorし、次のコマンドを実行します。

CREATE EXTENSION IF NOT EXISTS pg_diskann;

または、 vector 拡張機能の明示的な許可と作成をスキップし、代わりに前のコマンドを実行して、 CASCADE 句を追加することもできます。 その句 PostgreSQL は、依存する拡張機能に対して CREATE EXTENSION を暗黙的に実行します。 これを行うには、次のコマンドを実行します。

CREATE EXTENSION IF NOT EXISTS pg_diskann CASCADE;

現在接続しているデータベースから拡張機能を削除するには、次のコマンドを実行します。

DROP EXTENSION IF EXISTS pg_diskann;

diskann インデックス アクセス方法を使用する

拡張機能がインストールされたら、ベクトル データを含むテーブル列に diskann インデックスを作成できるようになります。 たとえば、embedding テーブルの demo 列にインデックスを作成するには、次のコマンドを使用します。

CREATE TABLE demo (
 id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
 embedding public.vector(3)
 -- other columns
);

-- insert dummy data
INSERT INTO demo (embedding) VALUES
('[1.0, 2.0, 3.0]'),
('[4.0, 5.0, 6.0]'),
('[7.0, 8.0, 9.0]');

-- create a diskann index by using Cosine distance operator
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

インデックスが作成されたら、クエリを実行して最も近い近隣ノードを見つけることができます。

次のクエリは、ベクトル [2.0, 3.0, 4.0]に最も近い 5 つの近隣を検索します。

SELECT id, embedding
FROM demo
ORDER BY embedding <=> '[2.0, 3.0, 4.0]'
LIMIT 5;

Postgres は、DiskANN インデックスを使用するタイミングを自動的に決定します。 インデックスを使用するシナリオでインデックスを使用しないことを選択した場合は、次のコマンドを実行します。

-- Explicit Transcation block to force use for DiskANN index.

BEGIN;
SET LOCAL enable_seqscan TO OFF;
-- Similarity search queries
COMMIT;

重要

enable_seqscanをオフに設定すると、他の方法が使用可能な場合は、プランナーがクエリ プランナーによるシーケンシャル スキャン プランの使用を禁止します。 SET LOCAL コマンドを使用すると無効になるため、現在のトランザクションに対してのみ設定が有効になります。 COMMIT または ROLLBACK の後、セッション レベルの設定が再度有効になります。 クエリに他のテーブルが含まれている場合、この設定では、すべてのテーブルでシーケンシャル スキャンを使用しないことをお勧めします。

量子化を使用して効率的にスケーリングする (プレビュー)

DiskANN は、製品量子化 (PQ) を使用して、ベクターのメモリ占有領域を大幅に削減します。 他の量子化手法とは異なり、PQ アルゴリズムはベクトルをより効果的に圧縮し、パフォーマンスを大幅に向上させることができます。  PQ を使用する DiskANN を使用すると、メモリ内のデータを増やすことができます。これにより、低速のストレージにアクセスする必要が減り、圧縮されたベクターを比較する際のコンピューティングの使用量も少なくなります。 これにより、大量のデータを処理する場合のパフォーマンスが向上し、コストが大幅に削減されます (> 100 万行)

製品量子化 (PQ) 機能にアクセスするには、 プレビューにサインアップしてください

インデックスの作成を高速化する

インデックスのビルド時間を短縮するには、いくつかの方法をお勧めします。

より多くのメモリを使用する

インデックスの作成を高速化するために、インデックス ビルド用に Postgres インスタンスに割り当てられているメモリを増やすことができます。 メモリ使用量は、 maintenance_work_mem パラメーターを使用して指定できます。

-- Set the parameters
SET maintenance_work_mem = '8GB'; -- Depending on your resources

CREATE INDEX コマンドは、使用可能なリソースに応じて、指定された作業メモリを使用してインデックスを作成します。

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

ヒント

インデックスの作成中にメモリ リソースをスケールアップしてインデックス作成の速度を向上させ、インデックス作成が完了したらスケール ダウンできます。

並列化の使用

インデックスの作成を高速化するために、並列ワーカーを使用できます。 ワーカーの数は、テーブルの作成時に、parallel_workers ステートメントの CREATE TABLE ストレージ パラメーターを使用して指定できます。 また、後で SET ステートメントの ALTER TABLE 句を使用して調整できます。

CREATE TABLE demo (
	id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
	embedding public.vector(3)
) WITH (parallel_workers = 4);
ALTER TABLE demo SET (parallel_workers = 8);

CREATE INDEX コマンドは、使用可能なリソースに応じて、指定された数の並列ワーカーを使用してインデックスを作成します。

CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)

重要

リーダー プロセスは、並列インデックス ビルドに参加できません。

並列ワーカーを使用してインデックスを作成する場合は、それに応じて max_parallel_workersmax_worker_processes、および max_parallel_maintenance_workers パラメーターも設定する必要があります。 これらのパラメーターの詳細については、 リソースの使用状況と非同期動作を制御するパラメーターを参照してください。

これらのパラメーターは、さまざまな粒度レベルで設定できます。 たとえば、セッション レベルで設定するには、次のステートメントを実行します。

-- Set the parameters
SET max_parallel_workers = 8;
SET max_worker_processes = 8; -- Note: Requires server restart
SET max_parallel_maintenance_workers = 4;

Azure Database for PostgreSQL フレキシブル サーバーでこれらのパラメーターを構成するその他のオプションについては、「 サーバー パラメーターの構成」を参照してください。

注意

max_worker_processes パラメーターを有効にするには、サーバーの再起動が必要です。

これらのパラメーターとサーバー上の使用可能なリソースの構成で並列ワーカーの起動が許可されていない場合、PostgreSQL は自動的にフォールバックして、非パラメーター モードでインデックスを作成します。

構成パラメータ

diskannインデックスを作成するときに、さまざまなパラメーターを指定して動作を制御できます。

インデックス パラメーター

  • max_neighbors: グラフ内のノードあたりのエッジの最大数 (既定値は 32)。 値を大きくすると、特定のポイントまでの呼び戻しが向上する可能性があります。
  • l_value_ib: インデックスのビルド中の検索リストのサイズ (既定値は 100)。 値が大きいほどビルドが遅くなりますが、インデックスの品質は高くなります。
  • pq_param_num_chunks: 製品量子化のチャンク数 (既定値は 0)。 0 は、埋め込みディメンションに基づいて自動的に決定されていることを意味します。 元の埋め込みサイズの 1/3 を使用することをお勧めします。
  • pq_param_training_samples: PQ ピボット テーブルをトレーニングするベクトルの数 (既定値は 0)。 0 は、テーブル サイズに基づいて自動的に決定されていることを意味します。
CREATE INDEX demo_embedding_diskann_custom_idx ON demo USING diskann (embedding vector_cosine_ops)
WITH (
 max_neighbors = 48,
 l_value_ib = 100,
 pq_param_num_chunks = 0,
 pq_param_training_samples = 0
 );

拡張パラメーター

  • diskann.iterative_search: 検索動作を制御します。

    diskann.iterative_searchの構成:

    • relaxed_order(既定値): 必要なタプルの数 (diskann.l_value_is 句によって制限される可能性がある) が生成されるまで、diskann がLIMITのバッチでグラフを繰り返し検索できるようにします。 結果が順不同になる可能性があります。

    • strict_order: relaxed_orderと同様に、目的のタプル数が生成されるまで、diskann でグラフを反復的に検索できます。 ただし、結果が厳密な順序で距離順に返されることが保証されます。

    • off: 非拡張検索機能を使用します。つまり、1 つのステップで diskann.l_value_is タプルをフェッチしようとします。 noniterative 検索は、diskann.l_value_is句またはクエリに一致するタプルの数に関係なく、クエリに対して最大のLIMIT ベクターのみを返すことができます。

    検索動作を strict_orderに変更するには、現在のセッションで実行されるすべてのクエリに対して、次のステートメントを実行します。

    SET diskann.iterative_search TO 'strict_order';
    

    現在のトランザクションで実行されているすべてのクエリにのみ影響するように変更するには、次のステートメントを実行します。

    BEGIN;
    SET LOCAL diskann.iterative_search TO 'strict_order';
    -- All your queries
    COMMIT;
    
  • diskann.l_value_is: インデックス スキャンの L 値 (既定値は 100)。 値を大きくすると、再現率は向上しますが、クエリの速度が低下する可能性があります。

    インデックス スキャンの L 値を 20 に変更するには、現在のセッションで実行されるすべてのクエリについて、次のステートメントを実行します。

    SET diskann.l_value_is TO 20;
    

    現在のトランザクションで実行されているすべてのクエリにのみ影響するように変更するには、次のステートメントを実行します。

    BEGIN;
    SET LOCAL diskann.l_value_is TO 20;
    -- All your queries
    COMMIT;
    
データセット のサイズ (行) パラメーターのタイプ 名前 推奨値
<100万 インデックスのビルド l_value_ib 100
<100万 インデックスのビルド max_neighbors 32
<100万 クエリ処理時間 diskann.l_value_is 100
 
1M-50M インデックスのビルド l_value_ib 100
1M-50M インデックスのビルド max_neighbors 64
1M-50M クエリ処理時間 diskann.l_value_is 100
 
>50M インデックスのビルド l_value_ib 100
>50M インデックスのビルド max_neighbors 96
>50M クエリ処理時間 diskann.l_value_is 100

注意

これらのパラメーターは、特定のデータセットとユース ケースによって異なる場合があります。 ユーザーは、特定のシナリオに最適な設定を見つけるために、さまざまなパラメーター値を試す必要がある場合があります。

CREATE INDEX と REINDEX の進行状況

PostgreSQL 12 以降では、 pg_stat_progress_create_index を使用して、CREATE INDEX または REINDEX 操作の進行状況を確認できます。

SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;

CREATE INDEX または REINDEX 操作が実行される可能性のあるフェーズの詳細については、 CREATE INDEX フェーズを参照してください。

インデックス アクセス関数の選択

ベクトル型を使用すると、保存されているベクトルに対して 3 種類の検索を実行できます。 クエリの実行時にデータベースがインデックスを考慮できるように、インデックスの適切なアクセス関数を選択する必要があります。

pg_diskann は、以下の距離演算子をサポートしています

  • vector_l2_ops: <-> ユークリッド距離
  • vector_cosine_ops: <=> コサイン距離
  • vector_ip_ops: <#> 内積

トラブルシューティング

エラー: assertion left == right failed left: 40 right: 0:

  • DiskANN GA バージョン v0.6.x では 、インデックス メタデータ形式の破壊的変更が導入されています。 v0.5.x で作成されたインデックスは、v0.6.x の挿入操作と前方互換性がありません。 古いインデックスを持つテーブルに挿入しようとすると、インデックスが有効な場合でもエラーが発生します。

  • このエラーが発生した場合は、 次の方法で解決できます。

    • オプション 1: インデックスに対する REINDEX または REDINDEX CONCURRENTLY ステートメントの実行。

    • オプション 2: インデックスを再構築する

      DROP INDEX your_index_name;
      CREATE INDEX your_index_name ON your_table USING diskann(your_vector_column vector_cosine_ops);
      
      

エラー: diskann index needs to be upgraded to version 2...:

  • このエラーが発生した場合は、次の方法で解決できます。
    • オプション 1: インデックスに対する REINDEX または REDINDEX CONCURRENTLY ステートメントの実行。

    • オプション 2:REINDEXには時間がかかる場合があるため、拡張機能には upgrade_diskann_index() と呼ばれるユーザー定義関数も用意されており、可能な場合はインデックスのアップグレードが高速化されます。

      インデックスをアップグレードするには、次のステートメントを実行します。

      SELECT upgrade_diskann_index('demo_embedding_diskann_custom_idx');
      

      データベース内のすべての diskann インデックスを現在のバージョンにアップグレードするには、次のステートメントを実行します。

      SELECT upgrade_diskann_index(pg_class.oid)
      FROM pg_class
      JOIN pg_am ON (pg_class.relam = pg_am.oid)
      WHERE pg_am.amname = 'diskann';