pgvector 使用時のパフォーマンスを最適化する方法 - Azure Database for PostgreSQL - フレキシブル サーバー (2023)

  • 記事

に適用されます: pgvector 使用時のパフォーマンスを最適化する方法 - Azure Database for PostgreSQL - フレキシブル サーバー (1)Azure Database for PostgreSQL - フレキシブル サーバー

ベクターこの拡張機能は、オープンソースのベクトル類似性検索を PostgreSQL に追加します。

この記事では、次の制限とトレードオフについて説明します。ベクターまた、パーティショニング、インデックス作成、および検索設定を使用してパフォーマンスを向上させる方法を示します。

拡張機能自体の詳細については、次を参照してください。pgvectorの基本。公式も参考にしてみてはいかがでしょうかお読みくださいプロジェクトの。

パフォーマンス

常にクエリ プランを調査することから始める必要があります。クエリがかなりの速さで終了する場合は、次を実行します。EXPLAIN (分析、詳細、バッファ)

EXPLAIN (ANALYZE、VERBOSE、BUFFERS) SELECT * FROM t_test ORDER BY embedding <-> '[1,2,3]' LIMIT 5;

実行に時間がかかりすぎるクエリの場合は、分析するキーワード。結果に含まれる詳細は少なくなりますが、即座に提供されます。

EXPLAIN (VERBOSE, BUFFERS) SELECT * FROM t_test ORDER BY embedding <-> '[1,2,3]' LIMIT 5;

サードパーティのサイトなどExplain.depesz.comクエリ プランを理解するのに役立ちます。答えてみるべきいくつかの質問は次のとおりです。

  • クエリは並列化されましたか?
  • インデックスは使用されましたか?
  • WHERE 句で部分インデックス定義と同じ条件を使用しましたか?
  • パーティショニングを使用した場合、不要なパーティションは削除されましたか?

OpenAI 埋め込みのように、ベクトルが長さ 1 に正規化されている場合。内積 (<=>) 最高のパフォーマンスを実現します。

並列実行

Explain Plan の出力で、次の項目を探します。計画された労働者ワーカーが起動されました(後者の場合のみ分析するキーワードが使用されました)。のmax_Parallel_workers_per_gatherPostgreSQL パラメータは、データベースが毎回起動できるバックグラウンド ワーカーの数を定義します。集める収集マージ計画ノード。この値を増やすと、インデックスを作成しなくても、正確な検索クエリが高速化される可能性があります。ただし、この値が高くても、データベースはプランの並列実行を決定しない場合があることに注意してください。

EXPLAIN SELECT * FROM t_test ORDER BY embedding <-> '[1,2,3]' LIMIT 3;
クエリプラン------------------------------------------------- -------------------------------------- リミット (コスト=4214.82..4215.16) rows=3 width=33) -> 収集マージ (cost=4214.82..13961.30 rows=84752 width=33) 計画されたワーカー数: 1 -> 並べ替え (cost=3214.81..3426.69 rows=84752 width=33) 並べ替えキー: ( (embedding <-> '[1,2,3]'::vector)) -> t_test での並列 Seq スキャン (コスト = 0.00..2119.40 行 = 84752 幅 = 33)(6 行)

インデックス作成

インデックスが存在しない場合、拡張機能は完全な検索を実行するため、パフォーマンスは犠牲になりますが、完全な再現が可能になります。

近似最近傍検索を実行するには、データにインデックスを作成します。これにより、実行パフォーマンスのために再現率が犠牲になります。

可能であれば、インデックスを作成する前に必ずデータをロードしてください。この方法でインデックスを作成する方が速く、結果として得られるレイアウトもより最適になります。

限界

  • 列にインデックスを付けるには、列にディメンションを定義する必要があります。次のように定義された列にインデックスを付けようとしています列ベクトルエラーが発生します:エラー: 列にディメンションがありません
  • インデックスを作成できるのは、最大 2000 次元の列のみです。より多くのディメンションを持つ列にインデックスを付けようとすると、次のエラーが発生します。エラー: ivfflat インデックスの列には 2000 を超える次元を含めることはできません

2000 次元を超えるベクトルを保存できますが、インデックスを付けることはできません。次元削減を使用して、制限内に収めることができます。あるいは、Azure Cosmos DB for PostgreSQL によるパーティション分割やシャーディングを利用して、インデックスを作成せずに許容可能なパフォーマンスを達成します。

リストとプローブ

ivフラット近似最近傍 (ANN) 検索のインデックスです。この方法では、逆ファイル インデックスを使用してデータセットを複数のリストに分割します。プローブ パラメーターは、検索するリストの数を制御します。これにより、検索速度は遅くなりますが、検索結果の精度が向上します。

プローブパラメータがインデックス内のリストの数に設定されている場合、すべてのリストが検索され、検索は正確な最近傍検索になります。この場合、すべてのリストを検索することは、データセット全体に対してブルート フォース検索を実行することと同じであるため、プランナーはインデックスを使用しません。

インデックス付け方法では、k-means クラスタリング アルゴリズムを使用してデータセットを複数のリストに分割します。各リストには、特定のクラスター中心に最も近いベクトルが含まれています。検索中に、クエリ ベクトルがクラスターの中心と比較され、どのリストに最近傍が含まれる可能性が最も高いかが判断されます。プローブ パラメーターが 1 に設定されている場合、最も近いクラスター中心に対応するリストのみが検索されます。

実行するプローブの数とリストのサイズに正しい値を選択すると、検索パフォーマンスに影響を与える可能性があります。始めるのに適した場所は次のとおりです。

  1. 使用リストに等しい行数 / 1000最大 100 万行のテーブルの場合、sqrt(行)より大きなデータセットの場合。
  2. ためにプローブ皮切りにリスト / 10最大 100 万行のテーブルの場合、sqrt(リスト)より大きなデータセットの場合。

の量リストインデックスの作成時に定義されます。リストオプション:

CREATE INDEX t_test_embedding_cosine_idx ON t_test USING ivfflat (vector_cosine_ops を埋め込む) WITH (リスト = 5000);

プローブは、接続全体またはトランザクションごとに設定できます (次を使用します)。ローカルに設定トランザクション ブロック内):

SET ivfflat.probes = 10;SELECT * FROM t_test ORDER BY embedding <=> '[1,2,3]' LIMIT 5; -- 10 個のプローブを使用しますSELECT * FROM t_test ORDER BY embedding <=> '[1,2,3]' LIMIT 5; -- 10 個のプローブを使用します
BEGIN;SET LOCAL ivfflat.probes = 10;SELECT * FROM t_test ORDER BY embedding <=> '[1,2,3]' LIMIT 5; -- 10 個のプローブを使用COMMIT;SELECT * FROM t_test ORDER BY embedding <=> '[1,2,3]' LIMIT 5; -- デフォルトの 1 つのプローブを使用します

インデックスタイプの選択

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

コサイン距離

コサイン類似度検索には、ベクトルコサインオプスアクセス方法。

CREATE INDEX t_test_embedding_cosine_idx ON t_test USING ivfflat (vector_cosine_ops を埋め込む) WITH (リスト = 100);

上記のインデックスを使用するには、クエリでコサイン類似度検索を実行する必要があります。これは<=>オペレーター。

EXPLAIN SELECT * FROM t_test ORDER BY embedding <=> '[1,2,3]' LIMIT 5;
クエリプラン------------------------------------------------- -------------------------------------------------- ---- 制限 (コスト=5.02..5.23 行=5 幅=33) -> t_test で t_test_embedding_cosine_idx を使用したインデックス スキャン (コスト=5.02..175.06 行=4003 幅=33) 並べ替え: (埋め込み <=> ' [1,2,3]'::vector)(3 行)

L2距離

L2 距離 (ユークリッド距離とも呼ばれます) には、ベクター_l2_opsアクセス方法。

CREATE INDEX t_test_embedding_l2_idx ON t_test USING ivfflat (vector_l2_ops を埋め込む) WITH (リスト = 100);

上記のインデックスを使用するには、クエリで L2 距離検索を実行する必要があります。これは、<->オペレーター。

EXPLAIN SELECT * FROM t_test ORDER BY embedding <-> '[1,2,3]' LIMIT 5;
クエリプラン------------------------------------------------- --------------------------------------------------制限 (コスト=5.02..5.23 行=5 幅=33) -> t_test で t_test_embedding_l2_idx を使用したインデックス スキャン (コスト=5.02..175.06 行=4003 幅=33) 順序指定: (embedding <-> '[1,2) ,3]'::vector)(3 行)

内部製品

内積の類似性については、ベクトル_ip_opsアクセス方法。

CREATE INDEX t_test_embedding_ip_idx ON t_test USING ivfflat (vector_ip_ops を埋め込む) WITH (リスト = 100);

上記のインデックスを使用するには、クエリで内積類似性検索を実行する必要があります。これは<#>オペレーター。

EXPLAIN SELECT * FROM t_test ORDER BY embedding <#> '[1,2,3]' LIMIT 5;
クエリプラン------------------------------------------------- --------------------------------------------------制限 (cost=5.02..5.23 rows=5 width=33) -> t_test で t_test_embedding_ip_idx を使用したインデックス スキャン (cost=5.02..175.06 rows=4003 width=33) Order By: (embedding <#> '[1,2) ,3]'::vector)(3 行)

部分インデックス

シナリオによっては、データの部分セットのみをカバーするインデックスを作成することが有益です。たとえば、プレミアム ユーザー専用のインデックスを構築する場合があります。

CREATE INDEX t_premium ON t_test USING ivfflat (vec Vector_ip_ops) WITH (lists = 100) WHERE tier = 'premium';

プレミアム層がインデックスを使用していることがわかります。

Explain select * from t_test where tier = 'premium' order by vec <#> '[2,2,2]';
クエリプラン------------------------------------------------- ------------------------------------ t_test で t_premium を使用したインデックス スキャン (コスト = 65.57..25638.05 行) =245478 width=39) 順序: (vec <#> '[2,2,2]'::vector)(2 行)

無料利用枠のユーザーには次のメリットがありません。

Explain select * from t_test where tier = 'free' order by vec <#> '[2,2,2]';
クエリプラン------------------------------------------------- ----------------------- ソート (コスト=44019.01..44631.37 行=244941 幅=39) ソートキー: ((vec <#> '[2 ,2,2]'::vector)) -> t_test での Seq Scan (コスト = 0.00..15395.25 行 = 244941 幅 = 39) フィルター: (tier = 'free'::text)(4 行)

データのサブセットのみにインデックスが付けられているということは、インデックスがディスク上で占有するスペースが少なくなり、検索が高速化されることを意味します。

PostgreSQL は、インデックスが安全に使用できるかどうかを認識できない可能性があります。どこ部分インデックス定義の句が、クエリで使用されている句と一致しません。この例のデータセットでは、層列の個別の値として、正確な値「free」、「test」、および「premium」のみが含まれています。を使用したクエリでも、「プレミアム」のような階層PostgreSQL はインデックスを使用していません。

select * from t_test where tier like 'premium' order by vec <#> '[2,2,2]'; を説明します。
クエリプラン------------------------------------------------- ----------------------- ソート (コスト=44086.30..44700.00 行=245478 幅=39) ソートキー: ((vec <#> '[2 ,2,2]'::vector)) -> t_test での Seq Scan (コスト = 0.00..15396.59 行 = 245478 幅 = 39) フィルター: (tier ~~ 'premium'::text)(4 行)

パーティショニング

パフォーマンスを向上させる 1 つの方法は、データセットを複数のパーティションに分割することです。今年またはおそらく過去 2 年間のデータを参照することが自然なシステムを想像できます。そのようなシステムでは、データを日付範囲で分割し、システムが読み取り可能なときにパフォーマンスの向上を活用できます。クエリされた年によって定義された関連するパーティションのみ。

パーティション化されたテーブルを定義しましょう。

CREATE TABLE t_test_partitioned(vec Vector(3), vec_date date default now()) 範囲 (vec_date) で分割します。

毎年のパーティションを手動で作成することも、Citus ユーティリティ関数 (Cosmos DB for PostgreSQL で利用可能) を使用することもできます。

select create_time_partitions( table_name := 't_test_partitioned',partition_interval := '1 year', start_from := '2020-01-01'::timestamptz, end_at := '2024-01-01'::timestamptz );

作成されたパーティションを確認します。

\d+ t_test_partitioned
パーティションテーブル "public.t_test_partitioned" 列 |タイプ |照合 | Null 可能 |デフォルト |ストレージ |圧縮 |統計目標 |説明----------+----------+----------+----------+--- -------+----------+---------------+--------------+--- ---------- ヴェック |ベクトル(3) | | | |拡張された | | | vec_date |日付 | | |今() |プレーン | | |パーティション キー: RANGE (vec_date)パーティション: t_test_partitioned_p2020 FOR VALUES FROM ('2020-01-01') TO ('2021-01-01')、t_test_partitioned_p2021 FOR VALUES FROM ('2021-01-01') TO (' 2022-01-01')、t_test_partitioned_p2022 FOR VALUES FROM ('2022-01-01') TO ('2023-01-01')、t_test_partitioned_p2023 FOR VALUES FROM ('2023-01-01') TO ('2024- 01-01')

パーティションを手動で作成するには:

CREATE TABLE t_test_partitioned_p2019 PARTITION OF t_test_partitioned FOR VALUES FROM ('2019-01-01') TO ('2020-01-01');

次に、クエリが実際に利用可能なパーティションのサブセットに絞り込まれることを確認します。たとえば、以下のクエリでは 2 つのパーティションにフィルタリングされています。

Explain Analysis select * from t_test_partitioned where vec_date between '2022-01-01' と '2024-01-01';
クエリプラン------------------------------------------------- -------------------------------------------------- -------------------------------------- 追加 (コスト=0.00) ..58.16 行=12 幅=36) (実際の時間=0.014..0.018 行=3 ループ=1) -> t_test_partitioned_p2022 t_test_partitioned_1 でのシーケンススキャン (コスト=0.00..29.05 行=6 幅=36) (実際の時間= 0.013..0.014 行=1 ループ=1) フィルター: ((vec_date >= '2022-01-01'::date) AND (vec_date <= '2024-01-01'::date)) -> Seq Scan t_test_partitioned_p2023 t_test_partitioned_2 (コスト = 0.00..29.05 行 = 6 幅 = 36) (実際の時間 = 0.002..0.003 行 = 2 ループ = 1) フィルター: ((vec_date >= '2022-01-01'::date) AND (vec_date <= '2024-01-01'::date)) 計画時間: 0.125 ミリ秒 実行時間: 0.036 ミリ秒

パーティション化されたテーブルにインデックスを付けることができます。

CREATE INDEX ON t_test_partitioned USING ivfflat (vec Vector_cosine_ops) WITH (lists = 100);
Explain Analysis select * from t_test_partitioned where vec_date between '2022-01-01' and '2024-01-01' order by vec <=> '[1,2,3]' limit 5;
クエリプラン------------------------------------------------- -------------------------------------------------- -------------------------------------------------- --------------------------------------- 制限 (コスト=4.13..12.20 行) =2 幅=44) (実際の時間=0.040..0.042 行=1 ループ=1) -> マージ追加 (コスト=4.13..12.20 行=2 幅=44) (実際の時間=0.039..0.040 行=1)ループ = 1) ソート キー: ((t_test_partitioned.vec <=> '[1,2,3]'::vector)) -> t_test_partitioned_p2022 t_test_partitioned_1 で t_test_partitioned_p2022_vec_idx を使用したインデックス スキャン (コスト = 0.04..4.06 行 = 1 幅 = 44) (実際の時間=0.022..0.023 行=0 ループ=1) 順序: (vec <=> '[1,2,3]'::vector) フィルタ: ((vec_date >= '2022-01- 01'::date) AND (vec_date <= '2024-01-01'::date)) -> t_test_partitioned_p2023 t_test_partitioned_2 で t_test_partitioned_p2023_vec_idx を使用したインデックス スキャン (コスト = 4.08..8.11 行 = 1 幅 = 44) (実際の時間 = 0.015..0.016 行=1 ループ=1) 順序指定: (vec <=> '[1,2,3]'::vector) フィルター: ((vec_date >= '2022-01-01'::date) AND (vec_date <= '2024-01-01'::date)) 計画時間: 0.167 ミリ秒 実行時間: 0.139 ミリ秒(11 行)

結論

おめでとうございます。最高のパフォーマンスを達成するためのトレードオフ、制限、ベスト プラクティスを学びました。ベクター

FAQs

Azure Database for PostgreSQLとは何ですか? ›

Azure Database for PostgreSQLは、PostgreSQL オープンソース リレーショナル データベースに基づく、Microsoft クラウドのリレーショナル データベース サービスです。

Azure PostgreSQLの暗号化は? ›

Azure Database for PostgreSQL サービスでは、保存データのストレージ暗号化に FIPS 140-2 認証済みの暗号モジュールが使用されます。 データ (バックアップを含む) は、クエリの実行中に作成される一時ファイルも含めて、ディスク上で暗号化されます。

Azure Database for PostgreSQLのフレキシブルサーバーのバックアップは? ›

フレキシブル サーバーでは、データベース ファイルの毎日のバックアップが自動的に実行され、トランザクション ログが継続的にバックアップされます。 バックアップは 7 日から最大 35 日まで保持できます。 データベース サーバーは、バックアップの保持期間内の任意の時点に復元できます。

Azureフレキシブルサーバーとは何ですか? ›

Azure Database for PostgreSQL - フレキシブル サーバーは、データベース管理機能と構成設定のよりきめ細かな制御と柔軟性を提供するように設計されたフル マネージド データベース サービスです。

Azure PostgreSQLの接続のセキュリティは? ›

Azure Database for PostgreSQL サーバーは既定でセキュリティ保護されるため、どの IP ホストがアクセスを許可されるかを指定するまで、データベース サーバーへのすべてのアクセスが阻止されます。 ファイアウォールは、各要求の送信元 IP アドレスに基づいてサーバーへのアクセス権を付与します。

PostgreSQLの一時ファイルとは何ですか? ›

一時ファイルは、バックエンドまたはセッション接続ごとに保存されるファイルです。 これらのファイルはリソースプールとして使用されます。

PostgreSQLのセキュリティ対策は? ›

不正アクセスを防ぐ5つの方法
  1. 1 ssh接続できないようにする ...
  2. 2 postgresユーザのパスワードを分かりにくいものに変える ...
  3. 3 PostgreSQLのPort番号を変更する ...
  4. 4 PostgreSQLのアクセス先を制限する ...
  5. 5 DBをプライベートネットワークにする
Feb 9, 2020

Azure Database for PostgreSQLのバックアップストレージはいくらですか? ›

Azure Database for PostgreSQL は、プロビジョニングされているサーバー ストレージの 100% までをバックアップ ストレージとして追加コストなしで提供します。 バックアップ ストレージを追加で使用した場合は、1 か月ごとに GB 単位で請求されます。

Azure SQL Databaseの手動バックアップは? ›

AzureのSQL Databaseのバックアップは、Azure上で自動的に実施されておりますので手動でのバックアップは不要となります。

Azure Database for PostgreSQLの自動バックアップは? ›

既定では、Azure Database for PostgreSQL によって、7 日間の既定の保持期間で、サーバー全体 (作成されたすべてのデータベースを含む) の自動バックアップが有効になります

AzureフレキシブルサーバーのIPアドレスは? ›

カスタム DNS サーバーを使用する場合は、DNS フォワーダーを使用して Azure Database for PostgreSQL - フレキシブル サーバーの FQDN を解決する必要があります。 フォワーダーの IP アドレスは、168.63.129.16 である必要があります。

テンポラリテーブルとは何ですか? ›

一時表(TEMPORARY TABLE)とはトランザクション終了時、またはセッション終了時にテーブル内のデータが削除されるテーブルです。 上記以外の特徴として、別のセッションからはテーブル内のデータが参照できない点、REDOログへの書き込みが無いため、INSERT処理が早い点があります。

Work_memとは何ですか? ›

work_mem

PostgreSQLの各プロセスが使用するソート用のメモリバッファです。

Azure SQL Databaseのリカバリ方法は? ›

Azure portal を使用してデータベースを特定の時点に復旧するには、データベースの概要ページを開き、ツール バーの [復元] を選択します。 バックアップ ソースを選択し、新しいデータベースを作成する特定の時点のバックアップ ポイントを選択します。

Azure SQL Databaseのバックアップ時間は? ›

Azure SQL Database では以下が作成されます。 毎週の完全バックアップ。 12 時間または 24 時間ごとの差分バックアップ。 約 10 分ごとのトランザクション ログ バックアップ

Azure SQL Databaseのバックアップ期間は? ›

バックアップは最大35日保管できますが、バックアップ先にAzure Backupを指定することで最大10年間保管することが可能です。 設定の注意点としては、SQL Databaseと同じサブスクリプション・リージョン・リソースグループにAzure Backupを配置する必要があります。

Azure PostgreSQLのリストア方法は? ›

Azure PostgreSQL データベースを復元する [バックアップ コンテナー] ->[バックアップ インスタンス] に移動します。 データベースを選択し、 [復元] をクリックします

ポイントインタイムリストアとは? ›

ポイントインタイム リストアでは、ブロック BLOB データを以前の状態に復元できるようにすることで、誤った削除や破損を防ぐことができます。 ポイントインタイム リストアは、ユーザーまたはアプリケーションによって誤ってデータが削除された場合や、アプリケーション エラーによってデータが破損した場合に役立ちます。

スナップショットとポイントインタイムリカバリの違いは何ですか? ›

スナップショットの復元」は、定期的に自動で取得したスナップショットや手動で取得したスナップショットの時点のサーバーを起動します。 「ポイントインタイムリカバリ」は、最も遅い復元可能な時刻と復元可能な最新時刻の間から任意の時点のサーバーを起動します。

RDS 特定時点への復元 いつまで? ›

保持期間はデフォルトでは 7 日間ですが、最大 35 日間に設定可能です。 保持期間中、特定時点への復旧を開始して、最大で復元可能な最新時刻 (Latest Restorable Time) まで、任意の秒数を指定することができます。

リカバリポイントとは何ですか? ›

復元ポイントとは、復元ポイント作成時のシステムファイルの状態を保存したもの。 PC が健全な状態時の保存がポイントです。 これを使うことで、時間を遡ってパソコンを以前の状態へ戻すことが可能となります。

References

Top Articles
Latest Posts
Article information

Author: Velia Krajcik

Last Updated: 23/09/2023

Views: 5253

Rating: 4.3 / 5 (54 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Velia Krajcik

Birthday: 1996-07-27

Address: 520 Balistreri Mount, South Armand, OR 60528

Phone: +466880739437

Job: Future Retail Associate

Hobby: Polo, Scouting, Worldbuilding, Cosplaying, Photography, Rowing, Nordic skating

Introduction: My name is Velia Krajcik, I am a handsome, clean, lucky, gleaming, magnificent, proud, glorious person who loves writing and wants to share my knowledge and understanding with you.