版本:latest

GV_GRAPH向量索引 ​

功能介绍 ​

GV_GRAPH是gv_index扩展提供的近似最近邻索引。它将向量组织为Vamana磁盘图,适合数据量较大、需要降低向量检索时延,并且能够接受近似结果的场景。

GV_GRAPH既可以用于ASTORE表,也可以用于USTORE表。索引默认在CPU上构建和查询;安装NPU版GaussVector组件后,可以用NPU加速构建阶段的图剪枝。NPU不参与查询,查询性能仍由CPU、磁盘和查询参数决定。

支持范围如下:

项目支持范围
向量类型vector,向量列必须声明维度
索引维度最大4096维。该限制仅适用于GV_GRAPH索引,不是vector数据类型的维度上限
距离度量L2距离、余弦距离
表存储格式ASTORE、USTORE
数据维护INSERT、UPDATE、DELETE、VACUUM

开始之前 ​

安装环境需要包含GaussVector组件和gv_index扩展。连接需要创建索引的数据库后,执行:

sql
CREATE EXTENSION IF NOT EXISTS gv_index;
SET enable_indexscan_optimization = on;

可以通过以下语句检查扩展和索引访问方法是否可用:

sql
SELECT extname FROM pg_extension WHERE extname = 'gv_index';
SELECT amname FROM pg_am WHERE amname = 'gv_graph';

说明

gv_index需要在每个使用GV_GRAPH的数据库中分别创建。enable_indexscan_optimization默认为off,并且只对当前会话生效;执行GV_GRAPH查询前,需要在当前会话中将其设置为on。

快速使用 ​

创建ASTORE索引 ​

以下示例创建一个ASTORE表和L2距离索引。storage_type = auto表示由GV_GRAPH识别表的存储格式,其余构建参数使用默认值。

sql
CREATE TABLE items (
    id bigint PRIMARY KEY,
    embedding vector(3) NOT NULL
) WITH (storage_type = astore);

INSERT INTO items VALUES
    (1, '[0.1,0.2,0.3]'),
    (2, '[0.2,0.3,0.4]'),
    (3, '[0.8,0.7,0.6]');

CREATE INDEX items_embedding_gv_idx
ON items
USING gv_graph (embedding vector_l2_ops)
WITH (storage_type = auto);

按L2距离从近到远查询:

sql
SET enable_indexscan_optimization = on;

SELECT /*+ indexscan(items items_embedding_gv_idx) */
       id,
       embedding <-> '[0.1,0.2,0.3]'::vector AS distance
FROM items
ORDER BY embedding <-> '[0.1,0.2,0.3]'::vector
LIMIT 10;

示例表的数据量很小,因此使用indexscan Hint明确指定索引,便于验证功能。实际业务中通常不需要添加Hint,由优化器根据数据量和代价选择执行计划。

可以使用EXPLAIN确认执行计划是否包含items_embedding_gv_idx:

sql
EXPLAIN
SELECT /*+ indexscan(items items_embedding_gv_idx) */ id
FROM items
ORDER BY embedding <-> '[0.1,0.2,0.3]'::vector
LIMIT 10;

创建USTORE索引 ​

USTORE表的建索引和查询方式相同,只需将表定义为USTORE。例如:

sql
CREATE TABLE ustore_items (
    id bigint PRIMARY KEY,
    embedding vector(3) NOT NULL
) WITH (storage_type = ustore);

CREATE INDEX ustore_items_embedding_gv_idx
ON ustore_items
USING gv_graph (embedding vector_cosine_ops)
WITH (storage_type = auto);

余弦距离索引需要使用vector_cosine_ops操作符类,并在查询中使用<=>操作符:

sql
SELECT id,
       embedding <=> '[0.1,0.2,0.3]'::vector AS distance
FROM ustore_items
ORDER BY embedding <=> '[0.1,0.2,0.3]'::vector
LIMIT 10;

支持的操作符类如下:

操作符类查询操作符距离度量
vector_l2_ops<->L2距离
vector_cosine_ops<=>余弦距离

建索引时选择的操作符类必须与查询中的距离操作符匹配,否则不能使用该索引。

设置构建参数 ​

创建索引时可以在WITH子句中设置以下参数:

参数取值范围默认值使用说明
storage_typeauto、astore、ustoreauto建议使用auto。显式设置astore或ustore时,取值必须与表的存储格式一致。
quantization_typelvq、pqlvq向量量化方式。先使用默认值;需要减小索引空间时,可使用业务数据测试pq的召回率后再决定是否切换。
graph_degree8~25696每个图节点的连接规模。增大取值通常有利于召回率,但会增加构建开销和索引空间。
subgraph_count1~641子图数量。取值大于1,并且enable_vector_copy和build_with_quantized_vector均为false时,系统会将build_with_quantized_vector按true处理并输出WARNING。
num_parallels1~6432构建索引使用的最大线程数。应根据可用CPU和同时运行的业务负载设置。
prune_algvamana、npu_knnvamana图剪枝算法。vamana使用CPU;npu_knn使用NPU,并且仅支持带NPU组件的单机版本。
enable_vector_copytrue、falsefalse是否在构建过程中复制原始向量。一般保持默认值。
build_with_quantized_vectortrue、falsefalse是否使用量化向量建图。开启后需要使用业务数据验证召回率。

这些参数决定索引的物理结构,在CREATE INDEX或REINDEX时生效。调整参数后,需要重建索引才能使新配置应用到索引数据。

使用NPU加速构建 ​

当单机安装环境包含NPU版GaussVector组件时,可以将prune_alg设置为npu_knn,使用NPU完成构建阶段的图剪枝。CPU版组件或多节点版本不支持该取值,应使用默认的vamana。

下面的示例选择0号和1号NPU,并将一次索引构建可使用的NPU显存限制为8GB:

sql
SET npu_device_mask = 3;
SET npu_device_max_mem = '8GB';

CREATE INDEX items_embedding_gv_npu_idx
ON items
USING gv_graph (embedding vector_l2_ops)
WITH (
    storage_type = auto,
    prune_alg = npu_knn,
    graph_degree = 96,
    num_parallels = 32
);

npu_device_mask是十进制位掩码,默认值为255,对应0至7号NPU。使用前应根据实际可用设备设置该参数;例如,1表示0号NPU,3表示0号和1号NPU。npu_device_max_mem的默认值为1GB,取值范围为2MB~1TB。

这两个参数均为会话级参数,应在执行CREATE INDEX或REINDEX的会话中设置。详细说明请参见npu_device_mask和npu_device_max_mem。

说明

NPU仅加速索引构建阶段的图剪枝。设置prune_alg = npu_knn不会改变查询的执行设备,也不会直接提升查询性能。

调整查询效果 ​

gv_graph_nprobes控制一次索引扫描最多返回给执行器的候选记录数,默认值为128,取值范围为1~65535。提高候选数通常能够改善召回率,但也会增加查询耗时。

该参数至少应设置为不小于SQL中的LIMIT。查询还有其他WHERE过滤条件时,可以适当增加候选数,避免候选记录在后续过滤后不足。

sql
SET enable_indexscan_optimization = on;
SET gv_graph_nprobes = 256;

SELECT id,
       embedding <-> '[0.1,0.2,0.3]'::vector AS distance
FROM items
ORDER BY embedding <-> '[0.1,0.2,0.3]'::vector
LIMIT 100;

如果执行计划没有使用GV_GRAPH索引,请依次检查:

  • 当前会话是否已设置enable_indexscan_optimization = on。
  • 查询是否包含向量距离ORDER BY表达式。
  • 查询操作符是否与索引的操作符类匹配。
  • 查询向量的维度是否与向量列定义一致。

维护索引 ​

  • 执行INSERT、UPDATE或DELETE时,GV_GRAPH会同步维护索引,不需要手工刷新。
  • 定期对ASTORE或USTORE表执行VACUUM,清理索引中的无效记录。
  • 调整构建参数后,使用REINDEX INDEX INDEX_NAME重建索引。

使用限制 ​

  • 只支持ASTORE和USTORE行存表。
  • 只支持单个vector列,不支持多列索引、INCLUDE列和唯一索引。
  • 向量列必须声明维度,GV_GRAPH最大支持4096维。
  • NULL向量不会写入索引。业务不需要NULL值时,建议将向量列定义为NOT NULL。
  • 只支持L2距离和余弦距离,不支持内积操作符类。
  • 索引扫描必须包含向量距离ORDER BY表达式。
  • NPU剪枝只支持带NPU组件的单机版本,并且只加速索引构建,不加速查询。