Nova 向量检索引擎

更新时间:
复制 MD 格式

Nova 是 AnalyticDB for PostgreSQL 7.0 的向量检索引擎,提供磁盘型 Novad 和内存型 Novam 两类索引。本文介绍 Nova 的功能特性、索引选型、容量评估、创建与查询方法、参数调优以及运维管理。

功能概述

什么是 Nova

Nova 是 AnalyticDB for PostgreSQL 7.0 内置的高性能向量检索引擎,提供磁盘型 Novad 和内存型 Novam 两类索引算法。Nova 在查询性能、存储效率和运维便捷性方面进行了深度优化,适用于大规模向量相似度检索场景,如 RAG(检索增强生成)、语义搜索和推荐系统。

核心能力

与传统的 HNSW 索引相比,Nova 提供以下增强能力:

能力

说明

自适应搜索

在查询速度和召回率之间自动取舍,无需手动调参即可获得良好的检索效果。

灵活的存储方案

Novad 将主要索引数据存储在磁盘,支持 RaBitQ、SQ8 等量化压缩方式以及 halfvec、bit、sparsevec、sq8vector 等多种向量类型,大幅降低存储成本。

Delta-Base 写入架构

将数据写入与主索引构建解耦,新数据先写入内存 Delta 文件,后台异步合并到主索引。写入积压时自动触发反压机制,保障系统稳定性。

并发创建索引

支持 CREATE INDEX CONCURRENTLY 语法,在业务正常读写期间创建索引,避免锁表。

INCLUDE 列

将额外列存入索引,查询命中这些列时可直接从索引返回结果,减少回表开销。

PCA 自动降维

支持按方差解释率自动选择目标维度,也支持手动指定维度,有效降低计算量和存储占用。

Autotune 自动调参

只需指定 topK 和目标召回率,系统自动评估并应用最优搜索参数。支持传入真实查询表进行精细调优,也可基于索引数据生成合成查询。

前提条件

快速开始

以下示例演示如何创建表、建立 Nova 索引并执行向量查询。

创建示例表

创建一个包含文本内容和向量列的示例表。

CREATE TABLE chunks (
    id SERIAL PRIMARY KEY,
    chunk VARCHAR(1024),
    intime TIMESTAMP,
    url VARCHAR(1024),
    feature REAL[]
) DISTRIBUTED BY (id);

示例返回

CREATE TABLE

创建 Nova 索引

使用默认算法 novamr(带 RaBitQ 量化的内存型索引)创建向量索引。RaBitQ 量化可显著降低内存占用。

-- 使用默认算法 novamr,RaBitQ 量化可显著降低内存占用
CREATE INDEX idx_feature_novamr ON chunks
USING ann(feature)
WITH (
    dim = 1536,
    distancemeasure = cosine
);

示例返回

CREATE INDEX

Novamr 当前固定使用 7 bit,不支持自定义 rabitq_bits

执行向量查询

使用 <=> 运算符计算余弦距离,返回最相似的 10 条结果。

SELECT id,
       chunk,
       feature <=> ARRAY[0.1, 0.2, ...]::real[] AS distance
FROM chunks
ORDER BY distance
LIMIT 10;

示例返回(以实际数据为准)

 id |       chunk        | distance
----+--------------------+----------
 12 | Nova 向量检索      |   0.0831
  7 | PostgreSQL 检索    |   0.1047
......
 31 | 混合检索实践       |   0.1284
(10 rows)

索引选型与容量

Novad 与 Novam 对比

Nova 提供 Novad(磁盘型)和 Novam(内存型)两类索引,适用于不同的业务场景:

  • Novad(磁盘型):HNSW 加速层常驻内存,IVF 聚类数据保存在磁盘。对内存依赖低,索引构建速度快,磁盘占用小,支持 RaBitQ 和 SQ8 量化。适合大规模数据、成本敏感的检索场景。

  • Novam(内存型):基于图索引构建。内存充足时,同等规格下查询性能优于 Novad;内存不足时会回退到磁盘访问。支持 RaBitQ 和 SQ8 量化,可在内存占用与召回率之间灵活调整。适合实时推荐等低延迟场景。

image

Novam 索引变体

算法名

说明

novam(或 novamflat

不带量化压缩的图索引,全精度存储。

novamr

带 RaBitQ 量化的图索引(默认算法,固定使用 7 bit,不支持自定义 rabitq_bits)。

novamsq8

带 SQ8 标量量化的图索引。

Novad 索引变体

算法名

说明

novad(或 novadr

带 RaBitQ 量化的分区索引(rabitq_bits 默认值为 1)。novad 和 novadr 要求向量维度至少为 32;低于 32 维时请使用 novadflat。

novadflat

不带量化压缩的分区索引。全精度存储,召回率最高。

novadsq8

带 SQ8 标量量化的分区索引。使用 sq8vector 列创建 novadflat 索引时自动启用。

容量评估

以下表格列出不同向量维度和计算资源下的建议数据量上限。实际容量受数据分布、查询模式等因素影响,建议根据业务需求进行压测验证。

Novad 容量参考

总计算资源

128 维

256 维

512 维

768 维

1024 维

1536 维

2048 维

8c

320M

160M

80M

50M

40M

26M

20M

16c

640M

320M

160M

100M

80M

60M

40M

32c

1.28B

640M

320M

200M

160M

120M

80M

128c

5.12B

2.56B

1.28B

800M

640M

480M

320M

Novam 容量参考

总计算资源

128 维

256 维

512 维

768 维

1024 维

1536 维

2048 维

8c

32M

16M

8M

5M

4M

2.6M

2M

16c

64M

32M

16M

10M

8M

5M

4M

32c

128M

64M

32M

20M

16M

10M

8M

128c

512M

256M

128M

80M

64M

40M

32M

向量类型与距离度量

支持的向量类型

Nova 支持多种向量数据类型,覆盖稠密向量、稀疏向量和二值向量等场景。

数据类型

说明

最大维度

real[](float4[])

单精度浮点数组

8,000

vector

pgvector 兼容的稠密向量类型

8,000

halfvec

半精度浮点向量,存储空间约为 vector 的一半

16,000

float2[]

半精度浮点数组

16,000

bit

二值向量,适用于哈希指纹等场景

256,000

sparsevec

pgvector 兼容的稀疏向量类型(最大非零元素 4,000)

1,000,000,000

svector

稀疏向量类型(最大非零元素 4,000)

1,000,000,000

sq8vector

SQ8 压缩向量,以 INT8 格式存储,节省内存

8,000

支持的距离度量

距离度量

参数值

SQL 运算符

说明

适用向量类型

欧氏距离(平方)

l2

<->

适用于图片相似度检索

vector, halfvec, float4[], float2[], int2[], sparsevec, svector, sq8vector

反内积距离

ip

<#>

向量归一化后可替代余弦相似度

vector, halfvec, float4[], float2[], int2[], sparsevec, svector, sq8vector, bit

余弦距离

cosine

<=>

适用于文本相似度检索

vector, halfvec, float4[], float2[], int2[], sparsevec, svector, sq8vector

曼哈顿距离

l1

<+>

L1 距离

vector, halfvec, sparsevec

杰卡德距离

jaccard

<%>

适用于集合相似度度量

bit

汉明距离

hamming

<~>

适用于二进制编码相似度

bit

特殊向量类型使用示例

halfvec(半精度向量)

halfvec 使用半精度浮点数存储,内存占用约为 vector 的一半,适合对内存敏感的高维向量场景。

-- 创建 halfvec 类型的表
CREATE TABLE chunks_half (
    id SERIAL PRIMARY KEY,
    feature halfvec(1536)
) DISTRIBUTED BY (id);

-- 创建索引
CREATE INDEX idx_half ON chunks_half
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novamr,
    distancemeasure = cosine
);

sq8vector(SQ8 压缩向量)

sq8vector 以 INT8 格式存储向量,进一步压缩内存。配合 Novam 或 Novad 索引使用。

-- 创建 sq8vector 类型的表
CREATE TABLE chunks_sq8 (
    id SERIAL PRIMARY KEY,
    feature sq8vector(1536)
) DISTRIBUTED BY (id);

-- 创建 Novam 内存型 SQ8 索引
CREATE INDEX idx_sq8 ON chunks_sq8
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novam,
    distancemeasure = cosine
);

-- 也可创建 Novad 磁盘型 SQ8 索引
-- sq8vector + novadflat 自动切换为 novadsq8
CREATE INDEX idx_sq8_disk ON chunks_sq8
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novadflat,
    distancemeasure = cosine
);

稀疏向量(svector)

Nova 使用 svector 存储稀疏向量。每个稀疏向量包含两组一一对应的数据:

  • indices:非零维度的编号(从 0 开始)。

  • values:对应维度的值。

例如,一个 8 维稀疏向量,索引 2、3、6 对应的值分别为 1.2、1.1、0.7,其余位置为 0:

SELECT '{"indices":[2,3,6],"values":[1.2,1.1,0.7]}'::svector(8);

示例返回

                       svector
------------------------------------------------------
 {"indices":[2,3,6],"values":[1.2,1.1,0.7]}
(1 row)
重要

indicesvalues 的元素数量必须相同,并按位置一一对应。svector(N) 使用从 0 开始的下标,有效范围为 [0, N-1]。例如,svector(8) 的有效下标为 0~7。

创建稀疏向量表示例并创建索引:

DROP TABLE IF EXISTS sparse_docs;

CREATE TABLE sparse_docs (
    id         BIGINT PRIMARY KEY,
    title      TEXT NOT NULL,
    category   TEXT NOT NULL,
    publish_at TIMESTAMP NOT NULL,
    embedding  svector(8) NOT NULL
) DISTRIBUTED BY (id);

INSERT INTO sparse_docs(id, title, category, publish_at, embedding) VALUES
    (1, 'PostgreSQL 全文检索', 'search',    '2024-01-01',
        '{"indices":[1,3,7],"values":[0.8,1.5,0.4]}'),
    (2, 'Nova 稀疏向量检索',  'search',    '2024-02-01',
        '{"indices":[2,3,6],"values":[1.2,1.1,0.7]}'),
    (3, '向量数据库实践',      'vector',    '2024-03-01',
        '{"indices":[1,4,7],"values":[0.9,1.3,1.0]}'),
    (4, '数据分析基础',        'analytics', '2024-04-01',
        '{"indices":[5,7],"values":[1.4,0.6]}'),
    (5, '混合检索方案',        'search',    '2024-05-01',
        '{"indices":[2,4,6,7],"values":[0.6,1.1,1.2,0.9]}');

-- 使用内积衡量相关性,创建稀疏向量索引
CREATE INDEX sparse_docs_embedding_idx
ON sparse_docs
USING ann (embedding)
WITH (
    algorithm = 'novam',
    distancemeasure = 'ip'
);

ANALYZE sparse_docs;

使用一个 8 维查询向量返回最相关的 3 条数据:

SELECT
    id,
    title,
    category,
    -(embedding <#>
        '{"indices":[2,3,6],"values":[1,1,0.5]}'::svector(8)
     ) AS score
FROM sparse_docs
ORDER BY embedding <#>
    '{"indices":[2,3,6],"values":[1,1,0.5]}'::svector(8)
LIMIT 3;

示例返回

id

title

category

score

2

Nova 稀疏向量检索

search

2.650

1

PostgreSQL 全文检索

search

1.500

5

混合检索方案

search

1.200

在上述查询中:

  • <#> 计算负内积。负内积越小,内积越大,相关性越高。

  • ORDER BY embedding <#> 查询向量 按相关性从高到低排序,并允许优化器使用 Nova 索引。

二值向量(bit)

bit 类型用于存储二值向量,适用于哈希指纹等场景。支持汉明距离和杰卡德距离。

-- 创建 bit 类型的表
CREATE TABLE chunks_bit (
    id SERIAL PRIMARY KEY,
    feature bit(256)
) DISTRIBUTED BY (id);

-- 使用汉明距离创建索引
CREATE INDEX idx_bit ON chunks_bit
USING ann(feature)
WITH (
    dim = 256,
    algorithm = novam,
    distancemeasure = hamming
);

创建索引

基本语法

CREATE INDEX [CONCURRENTLY] [index_name]
ON [schema_name].[table_name]
USING ann(column_name)
WITH (dim = <dimension>,
      algorithm = <algorithm>,
      distancemeasure = <measure>,
      ...);

创建 Novad 索引

以下示例创建一个磁盘型 Novad 索引,使用余弦距离度量。

重要

novad 和 novadr 要求向量维度至少为 32;低于 32 维时请使用 novadflat。

CREATE INDEX idx_feature_novad_cosine ON chunks
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novad,
    distancemeasure = cosine,
    nlist = 2048,
    accel_m = 32
);

创建 Novam 索引

以下示例创建一个内存型 Novam 全精度索引,使用欧氏距离度量。

CREATE INDEX idx_feature_novam_l2 ON chunks
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novam,
    distancemeasure = l2,
    hnsw_m = 32,
    hnsw_ef_construction = 200
);

并发创建索引

Nova 支持 PostgreSQL 的 CREATE INDEX CONCURRENTLY 语法。创建期间业务可继续读写,避免锁表影响在线服务。

CREATE INDEX CONCURRENTLY idx_chunks_feature_novad
ON chunks
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novad,
    distancemeasure = cosine,
    nlist = 2048
);
重要

CREATE INDEX CONCURRENTLY 不能在显式事务块中执行。执行后必须检查 pg_index.indisvalidindisready。如果任一为 false,不要使用该索引;请执行 DROP INDEX index_name 清理后重建。

INCLUDE 列

INCLUDE 可把额外列写入索引,命中这些列时减少回表:

CREATE INDEX [index_name]
ON [schema_name].[table_name]
USING ANN(column_name) INCLUDE (col1, col2, ...)
WITH (dim = <dimension>,
      algorithm = <algorithm>,
      distancemeasure = <measure>,
      ...);

使用示例

-- 将 id 和 url 列包含在索引中,支持 Index Only Scan 和 Index Scan 不回表
CREATE INDEX idx_feature_include ON chunks
USING ann(feature) INCLUDE (id, url)
WITH (
    dim = 1536,
    algorithm = novad,
    distancemeasure = cosine
);

PCA 降维

PCA 降维可在保留主要信息的前提下降低向量维度,减少计算量和存储占用。支持自动和手动两种方式。

重要

pca_dimauto_reduction 不能同时设置:自动降维只设置 auto_reduction,手动降维只设置 pca_dim

自动选择维度:按方差解释率自动选择目标维度(默认阈值 98%)。

CREATE INDEX idx_pca_auto ON chunks
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novamr,
    distancemeasure = cosine,
    auto_reduction = true
);

手动指定维度:通过 pca_dim 指定降维后的目标维度,目标维度需要需要为64的整数倍。

CREATE INDEX idx_pca ON chunks
USING ann(feature)
WITH (
    dim = 1536,
    algorithm = novamr,
    distancemeasure = cosine,
    pca_dim = 256
);

索引构建参数

基本参数

参数名

说明

默认值

取值范围

dim

向量维度(必填,或从列类型自动推断)

[1, 8192](视向量类型而定)

algorithm

索引算法

novamr

novam, novamflat, novamr, novamsq8, novad, novadflat, novadr, hnswflat

distancemeasure

距离度量算法

l2

l2, ip, cosine, l1, jaccard, hamming

Novam 构建参数

参数名

说明

默认值

取值范围

hnsw_m

图中每个节点的双向连接数。值越大图质量越好,构建时间越长。

16

[2, 100]

hnsw_ef_construction

构建时搜索候选集大小。值越大图质量越好,构建时间越长。需 ≥ 2 × hnsw_m。

64

[4, 1000]

rabitq_bits

Novamr 固定使用 7 bit,不支持自定义 rabitq_bits

7

不支持配置

Novad 构建参数

参数名

说明

默认值

取值范围

nlist

IVF 聚类列表数

1024

[2, 1073741824]

accel_m

加速层(中心点导航 HNSW)邻居数

16

[8, 1024]

accel_efc

加速层构建候选集大小

128

[1, 32768]

rabitq_bits

RaBitQ 量化比特数(仅 novad/novadr)

1

[1, 8]

PCA 参数

参数名

说明

默认值

取值范围

pca_dim

PCA 降维后的目标维度。0 表示不启用。

0

需小于原始维度,且为 64 的整数倍

auto_reduction

启用基于方差阈值的自动维度选择,与 pca_dim 二选一

false

true / false

pca_whitening

启用 PCA 白化

false

true / false

pca_random

启用 PCA 随机旋转

false

true / false

系统级构建参数

参数名

说明

默认值

取值范围

fastann.build_parallel_processes

索引构建的最大并行进程数

75% 计算节点资源

[1, 128]

fastann.nova_min_train_num

IVF 聚类的最小训练向量数

100000

[1, 100000000]

fastann.nova_cluster_iter

K-means 聚类迭代次数

10

[0, 100000]

查询与调优

参数优先级

Nova 搜索参数可以配置在两个位置:

配置方式

生效范围

有效期

会话级 GUC

当前数据库连接中的查询

连接断开后失效

索引级 Reloption

使用指定索引的查询

持续生效,直到重新设置或 RESET

Reloption 与会话 GUC 的对应关系如下:

索引级 Reloption

对应的会话级 GUC

适用索引

nova_ef_search

fastann.hnsw_ef_search

Novam

nova_max_scan_points

fastann.hnsw_max_scan_points

Novam

nova_nprobe

fastann.nova_nprobe

Novad

nova_rescore_amp

fastann.quantize_rescore_amp

Novam、Novad

查询时按以下规则取值:

索引 Reloption 状态

实际使用的参数

设置了具体值

使用索引 Reloption

未设置、已 RESET 或值为 -1

使用对应的会话 GUC

一句话概括:会话级 GUC 是当前连接的默认值;索引级 Reloption 可以为指定索引覆盖这个默认值。

例如,会话 GUC 为 80,某个索引的 Reloption 为 200:

查询使用的索引

实际使用值

设置了 Reloption 的索引

200

其他未设置 Reloption 的索引

80

-1 只表示继承会话 GUC,不是实际搜索值。

会话级查询参数

使用 SET fastann.<参数名> = <值>; 配置当前会话。若索引支持同名 reloption,则只有该 reloption 为 -1 或已 RESET 时才会使用会话值。

Novam 查询参数

参数名

说明

默认值

取值范围

fastann.hnsw_ef_search

HNSW 搜索时的动态候选集大小。最关键的 Novam 调优参数,值越大召回率越高,查询越慢。

100

[1, 1000]

fastann.sparse_hnsw_ef_search

稀疏向量搜索的 ef_search

200

[1, 1000]

fastann.hnsw_max_scan_points

HNSW 最大扫描点数

2000

[0, 10000000]

fastann.quantize_rescore_amp

量化索引(SQ/RaBitQ)的重排候选集放大倍数

1.0

[0.0, 1000.0]

Novad 查询参数

参数名

说明

默认值

取值范围

fastann.nova_nprobe

IVF 搜索时探测的聚类列表数。最关键的 Novad 调优参数,值越大召回率越高,I/O 越多。

5

[1, 100000]

fastann.nova_accel_query_efs

加速层查询时的 ef_search

128

[1, 32768]

fastann.novad_result_heap_factor

结果堆放大倍数

1.0

[1.0, 1000.0]

fastann.quantize_rescore_amp

RaBitQ 量化的重排放大倍数

1.0

[0.0, 1000.0]

通用查询参数

参数名

说明

默认值

取值范围

fastann.topk_amp

混合查询(向量 + 过滤条件)的 topK 放大倍数

10

[1, 1000]

fastann.nova_topk_amp_mul

计算节点 topK 乘数因子。计算节点 topK = topK × mul + add

1.0

[0.0, 1000.0]

fastann.nova_topk_amp_add

计算节点 topK 加数因子

0.0

[0.0, 1000.0]

索引级查询参数

当某个具体索引需要使用不同于会话默认值的搜索参数时,可为该索引设置 reloptions。其中索引级(reloption)查询参数 = -1 表示使用对应的会话级(GUC)查询参数。

Reloption

适用索引

继承的 GUC

默认值

取值范围

nova_ef_search

Novam

fastann.hnsw_ef_search

-1

-1 或 [1, 1000]

nova_max_scan_points

Novam

fastann.hnsw_max_scan_points

-1

-1 或 [0, 10000000] 范围内 500 的整数倍

nova_nprobe

Novad

fastann.nova_nprobe

-1

-1 或 [1, 100000]

nova_rescore_amp

Novam、Novad

fastann.quantize_rescore_amp

-1

-1 或 [0.0, 1000.0]

nova_autotune_topk

Novam、Novad

0

0 或 [1, 1000]

nova_autotune_recall

Novam、Novad

0

0 或 [0.90, 0.99]

重要

nova_autotune_topknova_autotune_recall 必须成对设置,用于记录或切换 Autotune 配置。详细用法请参见Autotune 自动调参

设置索引级参数

-- 固定 Novam 索引的搜索参数
ALTER INDEX idx_feature_novam_l2 SET (
    nova_ef_search = 200,
    nova_max_scan_points = 5000
);

-- 固定 Novad 索引的搜索参数
ALTER INDEX idx_feature_novad_cosine SET (
    nova_nprobe = 20
);

恢复继承会话 GUC

-- Novam 索引恢复继承会话 GUC
ALTER INDEX idx_feature_novam_l2
RESET (nova_ef_search, nova_max_scan_points);

-- Novad 索引恢复继承会话 GUC
ALTER INDEX idx_feature_novad_cosine
RESET (nova_nprobe);

配置示例

使用索引 reloptions 固定单个索引的搜索参数:

-- 固定 Novam 索引参数
ALTER INDEX idx_feature_novam_l2 SET (
    nova_ef_search = 200,
    nova_max_scan_points = 5000
);

-- 固定 Novad 索引参数
ALTER INDEX idx_feature_novad_cosine SET (
    nova_nprobe = 20
);

reloption 为 -1 或已 RESET 时,查询改用当前会话 GUC:

ALTER INDEX idx_feature_novam_l2
RESET (nova_ef_search, nova_max_scan_points);

SET fastann.hnsw_ef_search = 200;
SET fastann.hnsw_max_scan_points = 5000;

Autotune 自动调参

Autotune 可自动调优 Novam 和 Novad 的搜索参数。只需指定 topK 和目标召回率,系统会自动评估并应用最优参数配置。支持传入真实查询表进行精细调优,也支持基于索引数据生成合成查询。

调优任务异步执行,调用后立即返回 handle。传入多个 topK 或 target_recall 时,系统会评估全部组合。任务完成后,自动将索引的搜索参数设置为最大 topK、最大 target_recall 对应的配置。

image

启动调优

以下示例同时调优 topK = 10 和 100,目标召回率为 0.99。传入测试查询表 docs_eval_queries,可保证在该查询集上达到目标召回率。每个 topK 和 target_recall 组合分别保存一套配置;任务完成后,索引自动应用最大组合,即 topK = 100、target_recall = 0.99。

SELECT *
FROM fastann.nova_autotune(
    index_relation => 'public.docs_embedding_novam_idx'::regclass, -- 必填;无默认值;作用:指定待调优索引
    topk           => ARRAY[10, 100],                                        -- 必填;无默认值;作用:指定需要调优的 topK
    target_recall  => 0.99,                                        -- 可选;默认值:0.99;作用:指定目标召回率
    n_samples      => 100,                                              -- 可选;默认值:300;作用:指定采样查询数
    n_trials       => 100,                                               -- 可选;默认值:500;作用:指定候选配置试验数
    query_table    => 'public.docs_eval_queries'::regclass,           -- 可选;默认值:NULL;作用:指定测试查询表
    query_column   => 'embedding'                                   -- 可选;默认值:NULL;作用:指定查询向量列
) AS result(handle);

没有测试查询表时,省略 query_tablequery_column。系统会根据索引内部数据生成查询并拟合参数:

SELECT *
FROM fastann.nova_autotune(
    index_relation => 'public.docs_embedding_novam_idx'::regclass, -- 必填;无默认值;作用:指定待调优索引
    topk           => ARRAY[10, 100],                                        -- 必填;无默认值;作用:指定需要调优的 topK
    target_recall  => 0.99,                                        -- 可选;默认值:0.99;作用:指定目标召回率
    n_samples      => 100,                                              -- 可选;默认值:300;作用:指定采样查询数
    n_trials       => 100                                                -- 可选;默认值:500;作用:指定候选配置试验数
) AS result(handle);

示例返回

  handle
-----------
 123456790
(1 row)
重要

不传入 query_table 时,Autotune 不能保证实际查询的召回率。需要召回率保证时,应传入有代表性的查询表。

查看调优进度

使用 nova_autotune 返回的 handle 查看任务进度:

SELECT
    stage,
    query_count,
    work_done,
    work_total,
    updated_at
FROM fastann.nova_autotune_progress(
    handle => 123456789
);

示例返回

   stage    | query_count | work_done | work_total |       updated_at
------------+-------------+-----------+------------+------------------------
 evaluating |         300 |       126 |        500 | 2026-07-28 14:20:42+08
(1 row)

work_done / work_total 表示任务进度百分比。进度函数返回 0 行时,表示任务已结束或 handle 已不在活动状态,不代表调优失败;此时可通过 nova_autotune_status 查看已筛选的配置,并回读索引 Reloption。

手动切换参数配置

Autotune 会保存每组 topK 和 target_recall 对应的参数。查看索引已有的全部调优结果:

SELECT
    topk, target_recall, achieved, autotune_recall,
    ef_search, max_scan_points, nprobe, rescore_amp, applied
FROM fastann.nova_autotune_status(
    index_relation => 'public.docs_embedding_novam_idx'::regclass
)
ORDER BY topk, target_recall;

示例返回

 topk | target_recall | achieved | autotune_recall | ef_search | max_scan_points | nprobe | rescore_amp | applied
------+---------------+----------+-----------------+-----------+-----------------+--------+-------------+---------
   10 |          0.99 | t        |           0.992 |        80 |            3000 |      0 |         1.2 | f
  100 |          0.99 | t        |           0.991 |       240 |           12000 |      0 |         1.5 | t
(2 rows)

每组 topK 和 target_recall 对应一套参数配置,切换时必须同时指定两者:

-- 使用 topK=10 时达到 99% 召回率的配置
ALTER INDEX public.docs_embedding_novam_idx SET (
    nova_autotune_topk = 10,
    nova_autotune_recall = 0.99
);

-- 切换到 topK=100 时达到 99% 召回率的配置
ALTER INDEX public.docs_embedding_novam_idx SET (
    nova_autotune_topk = 100,
    nova_autotune_recall = 0.99
);
重要

一个索引同时只能运行一个 Autotune 任务。

Score Filter

Score Filter 在 ANN 扫描阶段按相似度或距离阈值淘汰候选,减少后续排序和返回的数据量。可通过 GUC 或 SQL Hint 启用。

参数名

说明

默认值

fastann_score_filter_switch

启用或禁用 Score Filter

禁用

fastann_score_filter_min

最小 Score 阈值

-3.40282e+38

fastann_score_filter_max

最大 Score 阈值

3.40282e+38

通过 SET 启用

下面的查询只返回余弦相似度大于 0.75 的 topK 结果:

SET fastann_score_filter_switch = on;
SET fastann_score_filter_min = 0.75;
RESET fastann_score_filter_max;

SELECT id,
       chunk,
       1 - (
           feature <=> ARRAY[0.1, 0.2, ...]::real[]
       ) AS score
FROM chunks
ORDER BY score
LIMIT 10;

示例返回(以实际数据为准)

SET
SET
RESET
 id |       chunk        | score
----+--------------------+-------
 12 | Nova 向量检索      | 0.921
  7 | PostgreSQL 检索    | 0.884
(2 rows)

需要限定分数区间时,同时设置上下限:

SET fastann_score_filter_switch = on;
SET fastann_score_filter_min = 0.75;
SET fastann_score_filter_max = 0.95;

通过 SQL Hint 启用

Hint 必须放在一次独立 SQL 调用的最前面,前面不要拼接 SET、RESET 或其他语句。设计上只影响当前语句;使用前请在同一连接中验证当前版本是否会影响后续查询。

/*+ SET(fastann_score_filter_switch on)
    SET(fastann_score_filter_min 0.75)
    SET(fastann_score_filter_max 0.95) */
SELECT id,
       chunk,
       1 - (
           feature <=> ARRAY[0.1, 0.2, ...]::real[]
       ) AS score
FROM chunks
ORDER BY score
LIMIT 10;

示例返回(以实际数据为准)

 id |       chunk        | score
----+--------------------+-------
 12 | Nova 向量检索      | 0.921
  7 | PostgreSQL 检索    | 0.884
(2 rows)

写入与运维

Delta-Base 写入架构

Nova 使用 Delta-Base 架构接收实时写入,将数据写入与主索引构建解耦:

  1. 新向量先写入内存映射的 Delta 文件,最多同时存在 3 个。

  2. 每个 Delta 文件最多保存 max_delta_vecs 个向量(默认约 100 万)。

  3. 后台 Flush 线程定期将 Delta 数据合并到主索引。

  4. 可调用 nova_flush_index() 手动触发合并。

  5. 可调用 nova_delta_stats() 查看 Delta 文件状态。

image

写入反压

当 Delta 文件接近容量上限时,系统自动限制写入速度,防止内存溢出。

参数名

说明

默认值

fastann.nova_backpressure_enable

启用写入反压

true

fastann.nova_backpressure_soft_fullness

软限阈值(Delta 填充比),超过后开始添加延迟

0.1

fastann.nova_backpressure_soft_delay_min_ms

软限最小延迟(毫秒)

5

fastann.nova_backpressure_soft_delay_max_ms

软限最大延迟(毫秒)

15

fastann.nova_backpressure_hard_fullness

硬限阈值(Delta 填充比),超过后阻塞写入

0.3

fastann.nova_backpressure_hard_timeout_ms

硬限最大等待时间(毫秒)

1000

索引统计信息

-- 查看索引统计信息
SELECT nova_stats(
    index_oid => 'idx_feature_novamr'::regclass::oid, -- 必填;无默认值;作用:指定 Nova 索引 OID
    metadata_only => true                             -- 可选;默认值:true;作用:是否只返回静态元数据
);

-- 查看 Delta 文件状态
SELECT *
FROM nova_delta_stats(
    'idx_feature_novamr'::regclass -- 必填;无默认值;作用:指定要查看的 Nova 索引
);

示例返回(节选,数值以实际索引为准)

nova_stats
--------------------------------------------------
{
  "metadata": {
    "dimensions": 1536,
    "metric_kind": "cosine",
    ...
  }
}
(1 row)

 gp_segment_id |      index_name       | delta_index | vectors | fullness
---------------+-----------------------+-------------+---------+----------
             0 | idx_feature_novamr    | {0,1}       | {120,0} | {0.12,0}
             1 | idx_feature_novamr    | {0,1}       | {98,0}  | {0.10,0}
(2 rows)

手动 Flush

手动触发 Delta 数据合并到主索引:

SELECT *
FROM nova_flush_index(
    index_relation => 'idx_feature_novamr'::regclass
);

示例返回

 gp_segment_id | success
---------------+---------
             0 | t
             1 | t
(2 rows)

REINDEX

使用标准 PostgreSQL REINDEX 命令重建 Nova 索引:

REINDEX INDEX CONCURRENTLY idx_feature_novamr;

示例返回

REINDEX

兼容性与限制

pgvector 兼容模式

pgvector 兼容模式提供 pgvector 0.8.2 的常用类型、运算符、索引语法和参数名。索引由 Nova 构建和查询,并非原生 pgvector 索引。兼容层与 USING ann 可在同一数据库中并存。

启用兼容模式

当前版本使用 pgvector 兼容模式前,请提交工单申请开通。开通完成后,普通用户即可创建和使用 pgvector 兼容索引。

如需使 <-> 返回与 pgvector 一致的欧氏距离,请在会话中设置 fastann.pgvector_compatibility = on;仅用于 TopK 排序且不读取距离值或按距离过滤时,无需设置。

索引语法与 Nova 后端

可直接使用 pgvector 索引语法,距离度量由运算符类确定:

CREATE INDEX docs_embedding_hnsw_idx
ON docs USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

CREATE INDEX docs_embedding_ivfflat_idx
ON docs USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 1024);

pgvector 语法

支持的列类型

Nova 后端

USING hnsw

vector、halfvec

novamsq8,内存型 SQ8 索引

USING hnsw

bit、sparsevec

novam,内存型全精度索引

USING ivfflat

vector、halfvec

维度 ≥ 32 时使用 novad(1 bit RaBitQ);< 32 时使用 novadflat

hnswivfflat 的算法及距离度量分别由访问方法和运算符类决定。即使同时指定 algorithmdistancemeasure,也不会改变上述映射。

支持的运算符类

访问方法

列类型

支持的运算符类

hnsw

vector

vector_l2_ops、vector_ip_ops、vector_cosine_ops

hnsw

halfvec

halfvec_l2_ops、halfvec_ip_ops、halfvec_cosine_ops

hnsw

sparsevec

sparsevec_l2_ops、sparsevec_ip_ops

hnsw

bit

bit_hamming_ops、bit_jaccard_ops

ivfflat

vector

vector_l2_ops、vector_ip_ops、vector_cosine_ops

ivfflat

halfvec

halfvec_l2_ops、halfvec_ip_ops、halfvec_cosine_ops

参数映射

pgvector 参数

Nova 参数

默认值

说明

m

hnsw_m

16

HNSW 节点最大邻居数,取值范围 2~100

ef_construction

hnsw_ef_construction

64

构建候选集大小,取值范围 4~1000,且不小于 2 × m

lists

nlist

1024

IVF 聚类数,取值范围 2~1073741824

hnsw.ef_search

fastann.hnsw_ef_search

100

两个名称引用同一会话参数,取值范围 1~1000

兼容 IVFFlat 查询通过 nova_nprobe 调整搜索范围;未设置时继承 fastann.nova_nprobe,默认值为 5。ivfflat.probesfastann.ivfflat_probes 对该兼容索引不生效。

限制

  • 不支持在 Nova 索引上使用 L1 运算符类。创建 vector_l1_opshalfvec_l1_ops 索引会报错。

  • sparsevec 的余弦运算符类暂不支持 Nova 索引。余弦检索需要将索引向量和查询向量归一化后按内积搜索,当前 Nova 构建链路尚未接通稀疏向量的归一化处理。请使用 L2 或内积替代。

  • ivfflat 仅支持 vectorhalfvec 的 L2、内积和余弦距离。

  • pgvector 语法映射到 Nova 后端,索引结构、量化方式、存储占用、召回率和性能特征与原生 pgvector 不完全相同。

  • svector 最多支持 10 亿维,最多包含 4,000 个非零值。indicesvalues 必须包含相同数量的元素。values 必须是有限数值,不能包含 NaNInfinity-Infinity

使用注意事项

Nova 会在后台执行 Delta 合并和图修复。即使没有业务请求,也可能占用系统资源。在资源规划时请考虑此因素。