Hologres のベクトル計算機能は、類似性検索、画像検索、シーン認識に役立ちます。この機能により、データ処理と分析が向上し、より精度の高い検索およびレコメンデーション機能を構築できます。このトピックでは、Hologres でベクトル計算を使用する方法を、完全な例を用いて説明します。
注意事項
Hologres V4.0 以降では、HGraph ベクトル検索アルゴリズムがサポートされています。
ベクトルインデックスは、列指向テーブルと行列ハイブリッドテーブルでのみサポートされています。行指向テーブルではサポートされていません。
ベクトルインデックスを持つテーブルを削除または再構築する場合 (例:Insert Overwrite を使用)、ごみ箱機能を有効にしないでください。ごみ箱内のテーブルは引き続きメモリを消費するためです。
ベクトルインデックスを作成した後、データインポート後のコンパクションプロセス中にマニフェストが構築されます。
メモリテーブル (Mem Table) 内のデータにはベクトルインデックスがありません。ベクトル検索リクエストを実行すると、このデータはブルートフォース計算を使用して処理されます。
Serverless Computing リソースを使用して、バッチデータインポートを実行できます。Serverless リソースは、データインポート中にコンパクションとインデックス構築を同期的に完了します。詳細については、「Serverless Computing を使用した読み取り/書き込みタスクの実行」および「Serverless Computing を使用したコンパクションタスクの実行」をご参照ください。
Serverless リソースを使用しない場合は、バッチでデータをインポートしたり、インデックスを変更したりした後に、手動で次のコマンドを実行してコンパクションをトリガーする必要があります。詳細については、「コンパクション (ベータ)」をご参照ください。
SELECT hologres.hg_full_compact_table('<schema_name>.<table_name>', 'max_file_size_mb=4096');Serverless Computing リソースを使用して、ベクトル検索クエリを実行することもできます。
ベクトルインデックスの管理
インデックスの作成
テーブルの作成時にベクトルインデックスを作成できます。構文は次のとおりです。
注:Hologres では、ベクターは float4 配列として表現されます。ベクトルディメンションは 1 次元配列の長さであり、次の構文の `array_length` で指定されます。
CREATE TABLE <table_name> (
<vector_column_name> float4[] CHECK (array_ndims(<vector_column_name>) = 1 AND array_length(<vector_column_name>, 1) = <dim>)
)
WITH (
vectors = '{
"<vector_column_name>": {
"algorithm": "<algorithm>",
"distance_method": "<distance_method>",
"builder_params": {
"<builder_parameters_name>": <value>
[, ...]
}
}
[ , "<vector_column_name_2>": { ... } ]
}'
);パラメーター:
パラメーター | 説明 |
table_name | 対象テーブルの名前。 |
vector_column_name | 対象ベクトル列の名前。 |
dim | 対象列のベクトルディメンション。 |
ベクトルインデックスの `vectors` パラメーターには、次の要件があります。
値は JSON 文字列である必要があります。トップレベルでは、インデックスを構築するベクトル列の名前を指定する `vector_column_name` キーのみがサポートされます。
`vector_column_name` キーの値は、ベクトルインデックスパラメーターを設定するために使用される JSON オブジェクトです。次のキーがサポートされています。
キー | 説明 |
algorithm | ベクトルインデックスアルゴリズム。このパラメーターは必須です。HGraph のみがサポートされています。 |
distance_method | ベクトル距離を計算するメソッド。このパラメーターは必須です。次の値がサポートされています。
注:ベクトル検索に使用される距離関数は、ベクトルインデックスの距離メソッドに対応している必要があります。ソート要件も満たす必要があります。そうでない場合、ベクトルインデックスは使用できません。 |
builder_params | インデックス構築のパラメーター。値は JSON 文字列である必要があります。パラメーターの詳細については、次のセクションをご参照ください。
|
`builder_params` パラメーターは、次のパラメーターをサポートします。
パラメーター | 説明 |
max_degree | インデックス構築プロセス中に、各頂点はその |
ef_construction | インデックス構築中の検索深度を制御します。このパラメーターはオプションです。デフォルト値は 400 です。値を大きくすると、インデックス構築中に頂点の近傍として考慮される候補の数が増加します。これにより、インデックスの精度が向上しますが、インデックス構築の時間と計算の複雑さも増加します。この値を 600 より大きく設定しないでください。 |
base_quantization_type | 低精度 HGraph インデックスの量子化メソッド。このパラメーターは必須です。次のメソッドがサポートされています。
|
use_reorder | 高精度 HGraph インデックスを使用するかどうかを指定します。このパラメーターはオプションです。デフォルト値は FALSE です。 |
precise_quantization_type | 高精度 HGraph インデックスの量子化メソッド。このパラメーターはオプションです。デフォルト値は fp32 です。この値を変更しないでください。次のメソッドがサポートされています。`base_quantization_type` よりも精度の高い量子化メソッドを選択してください。
|
precise_io_type | 高精度と低精度のハイブリッド HGraph インデックスの記憶媒体。このパラメーターはオプションで、`use_reorder` が TRUE の場合にのみ有効になります。デフォルト値は `block_memory_io` です。次の値がサポートされています。
|
インデックスの変更
構文は次のとおりです。
ALTER TABLE <table_name>
SET (
vectors = '{
"<vector_column_name>": {
"algorithm": "<algorithm>",
"distance_method": "<distance_method>",
"builder_params": {
"<builder_parameters_name>": <value>
[, ...]
}
}
}'
);インデックスの削除
-- テーブル内のすべての列のベクトルインデックスを削除
ALTER TABLE <table_name>
SET (
vectors = '{}'
);
-- テーブルの col1 列と col2 列の両方にベクトルインデックスがあり、col2 列のインデックスを削除する必要がある場合は、ALTER TABLE 文を実行して col1 列のインデックスのみを保持します。
ALTER TABLE <table_name>
SET (
vectors = '{
"col1": { ... }
}'
);インデックスの表示
`hologres.hg_table_properties` システムテーブルをクエリして、作成されたベクトルインデックスを表示できます。
SELECT
*
FROM
hologres.hg_table_properties
WHERE
table_name = '<table_name>'
AND property_key = 'vectors';ベクトルインデックスを使用したベクトル検索
ベクトル距離関数
Hologres のベクトル検索は、近似検索と厳密検索の両方をサポートしています。作成されたベクトルインデックスを使用してクエリを高速化できるのは、近似検索関数のみです。関数は、ベクトルインデックスの `distance_method` に対応している必要があります。厳密検索関数はベクトルインデックスを使用できません。
注:ベクトル距離関数は、すべてが定数のリクエストパラメーターをサポートしていません。
関数 | 検索タイプ | リクエストパラメーター | 戻り値 | 説明 |
approx_euclidean_distance | 近似検索 | float4[], float4[] | float4 | ユークリッド距離の近似検索関数。 |
approx_inner_product_distance | 近似検索 | float4[], float4[] | float4 | 内積の近似検索関数。 |
approx_cosine_distance | 近似検索 | float4[], float4[] | float4 | コサイン距離の近似検索関数。 |
euclidean_distance | 厳密検索 | float4[], float4[] | float4 | ユークリッド距離の厳密検索関数。 |
inner_product_distance | 厳密検索 | float4[], float4[] | float4 | 内積の厳密検索関数。 |
cosine_distance | 厳密検索 | float4[], float4[] | float4 | コサイン距離の厳密検索関数。 |
ベクトルインデックス使用の確認
実行計画を確認することで、SQL 文がベクトルインデックスを使用しているかどうかを判断できます。計画に「Vector Filter」が含まれている場合、インデックスは正常に使用されています。詳細については、EXPLAIN および EXPLAIN ANALYZE をご参照ください。
例:
SELECT id, approx_euclidean_distance (feature, '{0.1,0.2,0.3,0.4}') AS distance FROM feature_tb ORDER BY distance LIMIT 40;実行計画:
Limit (cost=0.00..182.75 rows=40 width=12) -> Sort (cost=0.00..182.75 rows=160 width=12) Sort Key: (VectorDistanceRef) -> Gather (cost=0.00..181.95 rows=160 width=12) -> Limit (cost=0.00..181.94 rows=160 width=12) -> Sort (cost=0.00..181.94 rows=40000 width=12) Sort Key: (VectorDistanceRef) -> Local Gather (cost=0.00..91.53 rows=40000 width=12) -> Limit (cost=0.00..91.53 rows=40000 width=12) -> Sort (cost=0.00..91.53 rows=40000 width=12) Sort Key: (VectorDistanceRef) -> Project (cost=0.00..1.12 rows=40000 width=12) -> Index Scan using Clustering_index on feature_tb (cost=0.00..1.00 rows=40000 width=8) Vector Filter: VectorCond => KNN: '40'::bigint distance_method: approx_euclidean_distance search_params: {NULL} args: {feature'{0.100000001,0.200000003,0.300000012,0.400000006}'::real[]} Query Queue: init_warehouse.default_queue Optimizer: HQO version 4.0.0
例
テーブルを作成します。
-- シャード数が 4 のテーブルグループを作成します。 CALL HG_CREATE_TABLE_GROUP ('test_tg_shard_4', 4); -- テーブルを作成します。 CREATE TABLE feature_tb ( id bigint, feature float4[] CHECK(array_ndims(feature) = 1 AND array_length(feature, 1) = 4) ) WITH ( table_group = 'test_tg_shard_4', vectors = '{ "feature": { "algorithm": "HGraph", "distance_method": "Cosine", "builder_params": { "base_quantization_type": "rabitq", "max_degree": 64, "ef_construction": 400, "precise_quantization_type": "fp32", "use_reorder": true, "max_total_size_to_merge_mb" : 4096 } } }' );データをインポートします。
-- (オプション) Serverless Computing を使用して、大量のオフラインデータインポートおよび抽出、変換、ロード (ETL) ジョブを実行します。インポート中にコンパクションとインデックス構築が同期的に完了します。 SET hg_computing_resource = 'serverless'; SET hg_serverless_computing_run_compaction_before_commit_bulk_load = on; INSERT INTO feature_tb SELECT i, array[random(), random(), random(), random()]::float4[] FROM generate_series(1, 100000) i; -- 不要な SQL 文が Serverless リソースを使用しないように、構成をリセットします。 RESET hg_computing_resource;近似ベクトル検索を実行します。
-- コサイン距離に基づいて上位 40 件の結果を計算します。 SELECT id, approx_cosine_distance (feature, '{0.1,0.2,0.3,0.4}') AS distance FROM feature_tb ORDER BY distance DESC LIMIT 40;厳密ベクトル検索を実行します。
-- 厳密検索ではベクトルインデックスを使用しないため、距離関数はベクトルインデックスの distance_method と同じである必要はありません。 SELECT id, cosine_distance (feature, '{0.1,0.2,0.3,0.4}') AS distance FROM feature_tb ORDER BY distance DESC LIMIT 40;
パフォーマンスチューニング
ベクトルインデックスの適切な使用
データ量が少ない場合 (数万行など) や、インスタンスに十分なコンピューティングリソースがある場合は、ベクトルインデックスを設定せず、ブルートフォース計算を使用してください。ベクトルインデックスは、ブルートフォース計算ではレイテンシーやスループットの要件を満たせない場合にのみ使用すべきです。理由は次のとおりです。
ベクトルインデックスには損失があります。結果の精度、つまりリコール率は 100% には達しません。
ベクトルインデックスは、リクエストされた数よりも少ない項目を返す場合があります。たとえば、`LIMIT 1000` のクエリが 500 項目しか返さないことがあります。
ベクトルインデックスを使用する場合は、次のように設定します。以下の例では、768 ディメンションのベクトルの単一列を持つ非パーティションテーブルを使用します。
レイテンシーの影響を受けやすいシナリオ:メモリ専用インデックスを使用します。インデックスの量子化メソッドを `sq8_uniform` または `rabitq` に設定します。単一シャードのデータ量は 500 万行を超えないようにしてください。
レイテンシーの影響を受けにくい、またはデータ量が多いシナリオ:ハイブリッドメモリディスクインデックスを使用します。インデックスの量子化メソッドを `rabitq` に設定します。単一シャードのデータ量は 3,000 万から 5,000 万行を超えないようにしてください。
注:複数の列にベクトルインデックスを設定する場合、単一シャードの推奨データ量を比例して減らす必要があります。ベクトルディメンションもこの推奨に影響します。
例:
-- ハイブリッドインデックスの完全な例
CREATE TABLE feature_tb (
id bigint,
feature float4[] CHECK(array_ndims(feature) = 1 AND array_length(feature, 1) = 4)
)
WITH (
table_group = 'test_tg_shard_4',
vectors = '{
"feature": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "rabitq",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"precise_io_type": "reader_io",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);
-- メモリ専用インデックスの完全な例
CREATE TABLE feature_tb (
id bigint,
feature float4[] CHECK(array_ndims(feature) = 1 AND array_length(feature, 1) = 4)
)
WITH (
table_group = 'test_tg_shard_4',
vectors = '{
"feature": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "sq8_uniform",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);リコール率の向上
このセクションでは、VectorDBBench データセットを例として、リコール率を向上させる方法について説明します。
リコール率には複数の要因が影響します。次のインデックスパラメーター設定により、デフォルトのシステムリコール率は通常 95% を超えることができます。
`base_quantization_type` は `rabitq` または `sq8_uniform` です。
`precise_quantization_type` は `fp32` です。
`max_degree` は `64` です。
`ef_construction` は `400` です。
`hg_vector_ef_search` はシステムのデフォルトである 80 に設定されています。
リコール率をさらに 99% 以上に高めるには、他のパラメーターを変更せずに `hg_vector_ef_search` を 400 に設定します。ただし、リコール率を向上させると、クエリのレイテンシーとコンピューティングリソースの使用量が増加します。
リコール率を 99.5% から 99.7% の範囲に高めるには、`max_degree`、`ef_construction`、および `hg_vector_ef_search` パラメーターをさらに調整できます。この調整により、クエリのレイテンシー、クエリリソースの消費、インデックス構築時間、およびインデックス構築リソースの消費が増加します。例:
`max_degree` = 96。
`ef_construction` = 500 または 600。
`hg_vector_ef_search` = 500 または 600。
適切なシャード数の設定
シャード数が多いほど、マニフェストファイルが増え、クエリのスループットが低下します。実際には、インスタンスのリソースに基づいて適切なシャード数を設定する必要があります。通常、シャード数はワーカーの数に設定できます。たとえば、64 コアのインスタンスの場合、シャード数を 4 に設定できます。単一クエリのレイテンシーを短縮するには、シャード数を減らすことができますが、これにより書き込みパフォーマンスも低下します。
-- ベクトルテーブルを作成し、シャード数が 4 のテーブルグループに配置します。
CALL HG_CREATE_TABLE_GROUP ('test_tg_shard_4', 4);
CREATE TABLE feature_tb (
id bigint,
feature float4[] CHECK(array_ndims(feature) = 1 AND array_length(feature, 1) = 4)
)
WITH (
table_group = 'test_tg_shard_4',
vectors = '{
"feature": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "sq8_uniform",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);ベクトルとスカラーのハイブリッドクエリシナリオ
フィルター条件付きのベクトル検索には、このセクションで説明するようないくつかの一般的なフィルタリングシナリオが存在します。
クエリシナリオ 1:文字列の列をフィルター条件として使用する
次のクエリがその例です。一般的なシナリオは、組織内で対応するベクトルデータを見つけることです。たとえば、クラス内で顔データを見つける場合などです。
SELECT(feature, '{1,2,3,4}') AS d FROM feature_tb WHERE uuid = 'x' ORDER BY d LIMIT 10;次の最適化を実行できます。
`uuid` を分散キーとして設定します。これにより、同じフィルター値を持つデータが同じシャードに保存されることが保証されます。クエリは単一のシャードにのみアクセスします。
`uuid` をテーブルのクラスタリングキーとして設定します。ファイル内のデータはクラスタリングキーでソートされます。
クエリシナリオ 2:時間フィールドをフィルター条件として使用する
次のクエリがその例です。通常、時間フィールドはベクトルデータをフィルタリングするために使用されます。時間フィールド `time_field` をテーブルのセグメントキーとして設定できます。これにより、データを含むファイルを迅速に見つけることができます。
SELECT xx_distance(feature, '{1,2,3,4}') AS d FROM feature_tb WHERE time_field BETWEEN '2020-08-30 00:00:00' AND '2020-08-30 12:00:00' ORDER BY d LIMIT 10;したがって、フィルター条件付きのベクトル検索の場合、`CREATE TABLE` 文は通常次のようになります。
-- 注:時間でフィルタリングしない場合は、time_field に関連するインデックスを削除できます。
CREATE TABLE feature_tb (
time_field timestamptz NOT NULL,
uuid text NOT NULL,
feature float4[] CHECK(array_ndims(feature) = 1 AND array_length(feature, 1) = 4)
)
WITH (
distribution_key = 'uuid',
segment_key = 'time_field',
clustering_key = 'uuid',
vectors = '{
"feature": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "sq8_uniform",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);よくある質問
Q:「Writting column: feature with array size: 5 violates fixed size list (4) constraint declared in schema」というエラーが報告されます。
A:このエラーは、feature ベクトル列に書き込まれたデータのディメンションが、テーブルで定義されたディメンションと一致しないために発生します。ダーティデータを確認してください。
Q:「The size of two array must be the same in DistanceFunction, size of left array: 4, size of right array: x」というエラーが報告されます。
A:このエラーは、`xx_distance(left, right)` の `left` のディメンションが `right` のディメンションと一致しないために発生します。
Q:Java を使用してベクトルデータを書き込むにはどうすればよいですか?
A:次のサンプル Java コードを使用できます。
private static void insertIntoVector(Connection conn) throws Exception { try (PreparedStatement stmt = conn.prepareStatement("INSERT INTO feature_tb VALUES(?,?);")) { for (int i = 0; i < 100; ++i) { stmt.setInt(1, i); Float[] featureVector = {0.1f,0.2f,0.3f,0.4f}; Array array = conn.createArrayOf("FLOAT4", featureVector); stmt.setArray(2, array); stmt.execute(); } } }Q:Proxima Graph インデックスを HGraph インデックスに変更するにはどうすればよいですか?
A:Proxima Graph インデックスを HGraph インデックスに変更するには、次の 2 つのステップを順番に実行する必要があります。
ステップ 1:テーブルから既存の Proxima Graph インデックスを削除します。SQL コマンドは次のとおりです。
CALL set_table_property ('<TABLE_NAME>', 'proxima_vectors', '{}');`<TABLE_NAME>` を実際のテーブル名に置き換えてください。ステップ 2:元の Proxima Graph インデックスが削除された後、HGraph インデックスを作成できます。詳細については、「インデックスの作成」をご参照ください。