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 万行> )、パフォーマンスが向上し、コストが大幅に削減されます。
重要
DiskANN での製品量子化のサポートは 、pg_diskann v0.6 以降で利用できます。
インデックスのサイズを小さくし、より多くのデータをメモリに収めるために、PQ を利用できます。
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann(embedding vector_cosine_ops)
WITH(
product_quantized=true
);
ベクターの再ランク付けで PQ を使用する場合の精度を向上する
完全ベクトルによる再ランク付けは、DiskANN と直積量子化 (PQ) などの近似最近傍 (ANN) 検索システムで使用される手法であり、元の非圧縮 (完全精度) ベクトルを使用して上位 N 個の取得候補を並べ替えて結果の精度を向上します。 この再ランク付け手法は、正確なベクトル類似性メトリック (コサインの類似性やユークリッド距離など) に純粋に基づいています。 この手法は、ランク付けモデルを使用した再ランク付けと同じではありません。
ベクトル類似性検索の速度と精度のバランスを取るために、DiskANN と直積量子化を使用してクエリを実行する場合、2 段階の再ランク付け戦略を実装して精度を向上することができます。
初期近似検索: 内部クエリでは、DiskANN を使用して、格納されている埋め込みとクエリ ベクターの間のコサイン距離に基づいて、上位 50 個の近似最近傍を取得します。 この手順は、DiskANN のインデックス作成機能を利用して、高速かつ効率的です。
正確な再ランク付け: 外側のクエリは、実際の計算距離によってこれらの 50 件の結果を並べ替え、最も関連性の高い上位 10 件の一致を返します。
この 2 つの手順のアプローチを使用した再ランク付けの例を次に示します。
SELECT id
FROM (
SELECT id, embedding <=> %s::vector AS distance
FROM demo
ORDER BY embedding <=> %s::vector asc
LIMIT 50
) AS t
ORDER BY t.distance
LIMIT 10;
注意
%s クエリ ベクターに置き換える必要があります。 azure_aiを使用して、Postgres で直接クエリ ベクターを作成できます。
このアプローチでは、速度 (近似検索) と精度 (完全なベクター再ランク付け) のバランスが取られ、データセット全体をスキャンすることなく高品質の結果が確保されます。
高次元埋め込みのサポート
高度なジェネレーティブ AI アプリケーションは、多くの場合、優れた精度を実現するために 、テキスト埋め込み 3-large などの高次元埋め込み モデルに依存しています。 ただし、 pgvector の HNSW などの従来のインデックス作成方法は、最大 2,000 次元のベクターに制限されており、これらの強力なモデルの使用が制限されています。
pg_diskann v0.6 以降、DiskANN では最大 16,000 次元のインデックス作成ベクトルがサポートされるようになりました。これにより、高精度 AI ワークロードの範囲が大幅に拡大されました。
重要
高次元のサポートを活用するには、製品量子化を有効にする必要があります。
推奨される設定:
-
product_quantized: true に設定します。 -
pq_param_num_chunks: 最適なパフォーマンスを得るために埋め込みディメンションの 3 分の 1 に設定します。 -
pq_param_training_samples: 明示的に設定しない限り、テーブル サイズに基づいて自動的に決定されます。
この機能強化により、高い再現率と精度を維持しながら、大規模なベクター データセット全体でスケーラブルで効率的な検索が可能になります。
インデックスの作成を高速化する
インデックスのビルド時間を短縮するには、いくつかの方法をお勧めします。
より多くのメモリを使用する
インデックスの作成を高速化するために、インデックス ビルド用に 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_workers、 max_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)。 値が大きいほどビルドが遅くなりますが、インデックスの品質は高くなります。 -
product_quantized: 製品の量子化を有効にして、より効率的な検索を行うことができます (既定値は false)。 -
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,
product_quantized=true,
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 | インデックスのビルド | product_quantized |
true |
| 1M-50M | クエリ処理時間 | diskann.l_value_is |
100 |
| >50M | インデックスのビルド | l_value_ib |
100 |
| >50M | インデックスのビルド | max_neighbors |
96 |
| >50M | インデックスのビルド | product_quantized |
true |
| >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';