Hologres のベクターコンピューティングは、類似性検索、画像検索、シーン認識など、さまざまなユースケースをサポートしています。ベクターコンピューティングを柔軟に活用することで、データ処理と分析を向上させ、より正確な検索およびレコメンデーション機能を実現できます。このトピックでは、Hologres でベクターコンピューティングを使用する方法を説明し、完全な例を含みます。
注意事項
HGraph ベクター検索アルゴリズムは、Hologres V4.0 以降でサポートされています。
ベクターインデックスは、列指向テーブルと行列表指向ハイブリッドテーブルにのみ作成できます。行指向テーブルはベクターインデックスをサポートしていません。
`INSERT OVERWRITE` などを使用してテーブルを削除または再構築する予定がある場合、ベクターインデックスを持つテーブルに対してごみ箱機能を有効にしないでください。ごみ箱内のテーブルはメモリを消費し続けます。
ベクターインデックスを作成した後、データインポート後のコンパクション中にマニフェストが構築されます。
メモリテーブル (Mem Table) に保存されているデータにはベクターインデックスがありません。このデータに対するベクター検索リクエストは、ブルートフォース計算を使用します。
バッチデータインポートには、サーバーレスコンピューティングリソースの使用を推奨します。サーバーレスリソースは、データインポート中にコンパクションとベクターインデックス構築を同時に実行します。詳細については、「読み取り/書き込みタスクを実行するためのサーバーレスコンピューティングの使用」および「コンパクションタスクを実行するためのサーバーレスコンピューティングの使用」をご参照ください。
サーバーレスリソースを使用していない場合は、バッチデータのインポートまたはインデックスの変更後に、次のコマンドを手動で実行してコンパクションをトリガーしてください。詳細については、「コンパクション (ベータ版)」をご参照ください。
SELECT hologres.hg_full_compact_table('<SCHEMA_NAME>.<TABLE_NAME>', 'max_file_size_mb=4096');サーバーレスコンピューティングリソースは、ベクター検索クエリをサポートしています。
ベクターインデックスの管理
インデックスの作成
構文:テーブル作成時にベクターインデックスを作成します。
説明:Hologres では、ベクターは `float4` 配列として表現されます。ベクターの次元は、このドキュメントで `array_length` と呼ばれる 1 次元配列の長さに対応します。
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` キーは 1 つだけ許可されます。
`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 の高精度インデックスの量子化メソッド。オプション。`use_reorder` が TRUE の場合にのみ有効です。デフォルト値:fp32。この値は変更しないでください。サポートされているメソッド:`base_quantization_type` よりも精度の高い量子化メソッドを選択してください。
|
precise_io_type | HGraph の高精度および低精度のハイブリッドインデックスの記憶媒体。オプション。`use_reorder` が TRUE の場合にのみ有効です。デフォルト値:`block_memory_io`。サポートされている値:
|
builder_thread_count | オプション。デフォルト値:4。書き込み中にベクターインデックスを構築するためのスレッド数を制御します。通常、調整は不要です。このパラメーターを増やすと CPU 使用率が高くなる可能性があるため、一般的なシナリオでは変更しないでください。このパラメーターを変更しても、インデックスの再構築はトリガーされません。 |
graph_storage_type | オプション。デフォルト値:`flat`。このパラメーターは、メモリ内のグラフインデックスの圧縮を制御します。サポートされている値:
説明 Hologres V4.0.10 以降でこのパラメーターがサポートされています。 |
extra_columns | 列情報をベクターインデックスに添付します。V4.1.1 からサポートされています。オプション。INT、BIGINT、SMALLINT 型の列のみがサポートされています。検索中、ターゲットテーブルの対応する列をクエリすることなく、インデックスから直接列の値を取得できるため、ベクター検索のパフォーマンスが向上します。例: |
インデックスの変更
構文:
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 は、作成されたベクターインデックスを表示するための `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` をご参照ください。
SQL の例:
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
例
テーブルの作成
-- Shard Count = 4 のテーブルグループを作成 CALL HG_CREATE_TABLE_GROUP ('test_tg_shard_4', 4); -- テーブルの作成 CREATE TABLE feature_tb ( id bigint not null, 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", "graph_storage_type": "compressed", "max_degree": 64, "ef_construction": 400, "precise_quantization_type": "fp32", "use_reorder": true, "extra_columns": "id", "max_total_size_to_merge_mb" : 4096 } } }' );データのインポート
-- (オプション) 大規模なオフラインデータインポートや 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 がサーバーレスリソースを使用しないように設定をリセットします。 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;説明ターゲットテーブルにパラメーター
"extra_columns": "id"が含まれている場合、この近似ベクター検索の例では、ターゲットテーブルの `id` 列をクエリすることなく、ベクターインデックスから直接 `id` 列の値を取得します。`EXPLAIN ANALYZE` の結果でvector_index_extra_columns_usedパラメーターを確認して、`extra_columns` を介して値を提供したマニフェストファイルの数を確認できます。厳密なベクター検索の実行
-- 厳密検索はベクターインデックスを使用しないため、距離計算関数はベクターインデックスの 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 not null,
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",
"graph_storage_type": "compressed",
"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 not null,
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",
"graph_storage_type": "compressed",
"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
クエリパラメーター (GUC):
hg_vector_ef_search:デフォルト値の 80 を使用します。このパラメーターは、検索中の候補リストのサイズを制御し、精度と速度のバランスを取ります。値を大きくすると精度が向上しますが、リソースのオーバーヘッドも増加します。
リコール率を 99% 以上にさらに高めるには、他のパラメーターを変更せずに SET 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。
適切なシャード数の設定
シャード数が多いとマニフェストファイルの数が増え、近似ベクタークエリのスループットが低下します。したがって、アプリケーションに適したシャード数を選択してください。通常、以下のガイドラインに従います。
ベクターデータ量に基づいて適切な計算リソース仕様を選択します。例として、768 次元のベクターについては、以下のガイドラインに従ってください。他の次元に固有の推奨事項については、「ベクターコンピューティングに推奨されるインスタンスタイプ」をご参照ください。
完全なインメモリインデックス:ワーカーあたり 500 万ベクター。
メモリとディスクのハイブリッドインデックス:ワーカーあたり 1 億ベクター。
計算リソースの仕様に基づいてシャード数を決定します。通常、シャード数はワーカーの数と同じに設定します。例えば、64 CU のインスタンスの場合、`shard_count` を 4 に設定します。
SQL 設定の例:
-- ベクターテーブルを作成し、Shard Count = 4 のテーブルグループに配置します CALL HG_CREATE_TABLE_GROUP ('test_tg_shard_4', 4); CREATE TABLE feature_tb ( id bigint not null, 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", "graph_storage_type": "compressed", "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` を分散キーとして設定します。これにより、同一のフィルター済みデータが同じシャードに配置されるため、単一のクエリは 1 つのシャードにしかアクセスしません。
`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;したがって、フィルター条件付きのベクター検索の場合、典型的なテーブル作成ステートメントは次のようになります。
-- 注:時間でフィルターしない場合は、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",
"graph_storage_type": "compressed",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);サーバーレスリソースを使用したインデックスの再構築
テーブルプロパティを変更すると、コンパクションとインデックスの再構築がトリガーされ、高い CPU 消費が発生する可能性があります。以下のテーブルプロパティを変更するには、次のように進めてください。
`bitmap_columns`、`dictionary_encoding_columns`、またはベクターインデックスへの変更は、コンパクションとインデックスの再作成をトリガーします。これらの変更には `ALTER TABLE xxx SET` 構文を避け、代わりにサーバーレスコンピューティングリソースで `REBUILD` 構文を使用することを推奨します。詳細については、「REBUILD」をご参照ください。
ASYNC REBUILD TABLE <table_name>
WITH (
rebuild_guc_hg_computing_resource = 'serverless'
)
SET (
bitmap_columns = '<col1>,<col2>',
dictionary_encoding_columns = '<col1>:on,<col2>:off',
vectors = '{
"<col_vector>": {
"algorithm": "HGraph",
"distance_method": "Cosine",
"builder_params": {
"base_quantization_type": "rabitq",
"graph_storage_type": "compressed",
"max_degree": 64,
"ef_construction": 400,
"precise_quantization_type": "fp32",
"use_reorder": true,
"max_total_size_to_merge_mb" : 4096
}
}
}'
);JSON 形式のデータの列指向ストレージまたはフルテキストインデックス列を変更する場合も、コンパクションとインデックスの再構築がトリガーされます。これらの変更には REBUILD 構文はまだサポートされていません。代わりに、次のように一時テーブルを作成します。
BEGIN ;
-- 潜在的な一時テーブルをクリーンアップ
DROP TABLE IF EXISTS <table_new>;
-- 一時テーブルを作成
SET hg_experimental_enable_create_table_like_properties=on;
CALL HG_CREATE_TABLE_LIKE ('<table_new>', 'select * from <table>');
COMMIT ;
-- 対応する列に対して JSON 形式データの列指向ストレージを有効化
ALTER TABLE <table_new> ALTER COLUMN <column_name> SET (enable_columnar_type = ON);
-- 対応する列にフルテキストインデックスを作成
CREATE INDEX <idx_name> ON <table_new> USING FULLTEXT (column_name);
-- 一時テーブルにデータを挿入し、サーバーレスリソースを使用して実行し、インデックス構築を同期的に完了
SET hg_computing_resource = 'serverless';
INSERT INTO <table_new> SELECT * FROM <table>;
ANALYZE <table_new>;
BEGIN ;
-- 古いテーブルを削除
DROP TABLE IF EXISTS <table>;
-- 一時テーブルの名前を変更
ALTER TABLE <table_new> RENAME TO <table>;
COMMIT ;`distribution_key`、`clustering_key`、`segment_key`、ストレージ形式など、その他のプロパティ変更には、サーバーレスコンピューティングリソースで REBUILD 構文を使用します。
よくある質問
Q:エラー:「Writing 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 インデックスを作成します。詳細な手順については、「インデックスの作成」をご参照ください。