PROD欧洲主权BaaS平台打开仪表板 →

原生人工智能 · 9 最小读取值

Postgres 中的 HNSW 索引:矢量搜索的索引

Affane Daylami · Fondateur · 2026年4月6日

返回博客

HNSW 是 pgvector 推荐用于 Postgres 上相似向量搜索的索引算法。本指南展示了如何创建正确调整的 HNSW 索引。三个选择很重要:根据嵌入大小的列类型、构造时的 m 和 ef_construction 参数,以及每次请求时的 ef_search 来仲裁召回和延迟。

该英文文本是根据法文原文自动生成的,尚未经过审查。
该页面已自动翻译。英文版具有权威性。

Aurabase 的本机矢量搜索(RAG、pgvector、嵌入)依赖于相同的索引机制,在 Postgres 上的 Native AI页面上详细描述。本指南假设 Postgres 表已安装 pgvector、类型为 vector的列以及至少几千行。下面,简单的顺序扫描通常比近似索引更快。

要点

  • 与 IVFFlat 不同,HNSW 不需要任何训练阶段:索引是通过插入构建的,自 0.5.0 版本起在 pgvector 中可用。
  • 有两个参数设置构造时索引的质量:m(每个节点的连接数,默认 16)和 ef_construction(构造时的搜索宽度,默认 64)。
  • 第三个参数 hnsw.ef_search (pgvector 默认值:40)针对每个请求进行调整,无需重建索引,以仲裁召回和延迟。
  • pgvector 将 vector 类型的 HNSW 索引上限限制为 2000 个维度。除此之外(例如,具有 3072 维的嵌入),需要强制转换为 halfvec 才能建立索引。
  • pgvector 0.8.6 是嵌入 Aurabase Postgres 租户映像中的版本,于 2026 年 8 月 24 日直接在 Dockerfile 中验证。
#
了解

pgvector 中的 HNSW 索引是什么?

HNSW 代表分层可导航小世界。它是一个图索引:每个向量成为连接到其最近邻居的节点,组织在几个叠加层中。搜索从图的顶部最稀疏的层开始,然后逐层向下到最相关的邻居。因此,搜索时间几乎是对数的,而不是与行数呈线性关系。

IVFFlat 是 pgvector 的另一个索引,其工作方式有所不同:它将向量空间划分为由现有样本的训练过程确定的列表,然后才能对任何内容进行索引。 HNSW没有这个约束,每次插入都直接丰富了图,这使得对连续增长的表进行操作变得更简单。另一方面,与相同卷上的等效 IVFFlat 相比,HNSW 索引消耗更多内存并且需要更多时间来构建。

pgvector 在 0.5.0 版本中引入了 HNSW 支持。更高版本为本指南添加了有用的功能:halfvec 类型 (0.7.0) 用于索引超过 2000 个维度,以及 hnsw.iterative_scan 参数 (0.8.0) 用于提高筛选查询的召回率。如果您在决定之前将 pgvector 与专用向量库进行比较,我们的 比较 pgvector 与 Pinecone、Weaviate 和 Qdrant 详细说明了权衡。

#
步骤1

创建索引之前检查您的 pgvector 版本

首先确认安装的pgvector版本。太旧的扩展会导致本指南中的某些功能无提示地失败,特别是 halfvec 和 hnsw.iterative_scan。

psqlsql
SELECT extversion FROM pg_extension WHERE extname = 'vector';

HNSW 自 pgvector 0.5.0 起就存在。 halfvec类型是索引超过 2000 个维度的嵌入所必需的,至少需要 0.7.0 版本。 hnsw.iterative_scan 参数请求版本 0.8.0。

在 Aurabase 项目上,不会出现这个问题:Postgres 映像嵌入 pgvector 0.8.6,既在共享 Postgres 集群(docker/Postgres.Dockerfile,直接构建于 pgvector/pgvector:0.8.6-pg16-bookworm)上,又在每个项目专用的 Postgres 16 CNPG 实例上(docker/Postgres.CNPG.Dockerfile,继承了官方的 pgvector 0.8.6 ) CloudNativePG 图像)。已于 2026 年 8 月 24 日在两个 Dockerfile 中进行验证。

#
步骤2

根据嵌入的大小选择正确的列类型

列类型取决于嵌入的大小,而不仅仅是生成它们的模型。 pgvector 以 vector类型存储经典向量,存储空间上限为 16,000 维。但此类型的 HNSW 索引仅限于 2000 个维度:超出此范围,CREATE INDEX 会失败。

常见的嵌入模型通常会超过此阈值:来自 OpenAI 的 text-embedding-3-large 或来自 Google 的 gemini-embedding-2 本身可生成高达 3072 维的数据。要使用 HNSW 索引这些向量,请将列转换为 halfvec (存储精度减半),这将索引限制远远超出 2000 维。

尺寸专栏向量上的 HNSW需要铸造
768嵌入_768是的否
1536嵌入_1536是的否
3072嵌入_3072否(> 2000 暗淡)是的,演员::halfvec(3072)

Aurabase RAG 引擎说明了生产中的这种妥协:支持三类维度(768、1536、3072),存储在同一 embeddings表的三个不同列中。列 768 和 1536 直接在 HNSW 中以 vector类型进行索引。列 3072 通过 ::halfvec(3072)转换进行索引,精确地规避 2000 维上限。

migration.sqlsql
CREATE INDEX idx_embeddings_vec_768 ON embeddings
  USING hnsw (embedding_768 vector_cosine_ops)
  WHERE embedding_768 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_1536 ON embeddings
  USING hnsw (embedding_1536 vector_cosine_ops)
  WHERE embedding_1536 IS NOT NULL;

CREATE INDEX idx_embeddings_vec_3072 ON embeddings
  USING hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  WHERE embedding_3072 IS NOT NULL;

For details of ingestion (chunking, call to the embedding provider, insertion), see the RAG pipeline tutorial on pgvector.

#
步骤3

使用 m 和 ef_construction 参数创建索引

对于第一个索引,使用 pgvector 的默认值,最小语法就足够了。

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops);

pgvector 然后应用 m = 16 和 ef_construction = 64。要显式调整这些值,请使用 WITH 子句:

psqlsql
CREATE INDEX ON items
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 24, ef_construction = 100);
加快推进重大建设

在大表上构建 HNSW 索引之前,暂时增加会话的 maintenance_work_mem :根据 pgvector 文档本身,这是减少构建时间的最直接手段。

参数m改变了什么?

m 设置图中每个节点每层维护的最大连接数。较高的值会使图形更加稠密:召回率增加,但消耗的内存和构建时间也会增加,近似线性。默认值 (16) 适用于大多数情况。在大型嵌入中,达到 24 或 32 尤其合理,因为近邻和远邻之间的区别会变得更精细。

ef_construction 改变了什么?

ef_construction 设置索引构建期间为每个插入节点探索的候选列表的大小。较高的值可以提高最终图表的质量,从而提高潜在的召回率,但代价是较长的构建时间。与 m不同,此参数在查询时没有成本:它是一次性投资,仅在创建索引时支付一次。

同一个表中多个维度类的部分索引

当表存储多个向量列(每个维度类一个,如 Aurabase 那样)时,请使用 WHERE colonne IS NOT NULL子句单独为每列建立索引。这种部分索引避免了为给定行未使用的类建立空行索引,从而减少了索引的大小并加快了其构建速度,而无需任何召回成本。

运算符类(vector_cosine_ops、 vector_l2_ops 或 vector_ip_ops)的选择必须与训练嵌入模型的指标相对应。最近的文本嵌入模型都针对余弦相似性进行了训练:因此,vector_cosine_ops(或强制转换列上的 halfvec_cosine_ops)是最安全的默认选择。

ef_search 在每个查询上设置,而不是在构建索引时设置。它设置搜索过程中探索的候选列表的大小:它越高,召回率就越好,但代价是延迟更长。 pgvector 将其默认值设置为 40。

psqlsql
SET LOCAL hnsw.ef_search = 100;

SELECT id, content
FROM embeddings
ORDER BY embedding <=> '[...]'::vector
LIMIT 10;

一旦查询将向量搜索与扫描索引(在命名空间、租户或任何其他元数据标准上)后应用的 WHERE 过滤器结合起来,40 就远远不够了。 HNSW 扫描带回 ef_search 原始候选者,然后过滤器丢弃其中的一部分。如果幸存下来的候选者太少,最终的 LIMIT 最终会出现填充不足的情况。

因此,Aurabase RAG 引擎根据请求的 top_k动态扩展 ef_search ,而不是保留固定值 40: ef = max(top_k × 4, 64)。使用 ef_search = 64搜索 5 个最接近的结果;搜索前 50 名使用 ef_search = 200。对于需要另一个召回/延迟权衡的部署,此公式仍然可以根据环境变量进行调整。

pgvector 0.8 针对同一问题添加了第二个杠杆: hnsw.iterative_scan。在 strict_order 或 relaxed_order模式下,搜索逐渐扩大其搜索范围,直到过滤后收集到足够的结果,而不是停在固定的候选列表上。 Aurabase 默认在 strict_order中激活它,但在保存点中保护调用。在 0.8 之前的 pgvector 版本中,如果不存在此参数,则查询会继续以降级模式而不是失败。

#
走得更远

构建完整的 RAG 管道

这个 HNSW 索引只是完整 RAG 管道的一部分:分块、嵌入生成、摄取,然后搜索。我们的 分步教程 在 pgvector 上端到端构建此管道,从第一次插入到相似性查询。 技术文档 还详细介绍了 Aurabase 在 Postgres 上构建的所有本机 AI 功能。

#
常见问题解答

常见问题解答

HNSW 或 IVFFlat:使用 pgvector 选择哪一个?+
HNSW 适用于生产中的绝大多数向量搜索案例:在同等延迟下更好的召回,无需事先训练阶段,并且对持续增长的表有良好的容忍度。当可用内存非常有限时,IVFFlat 仍然具有相关性,但如果数据分布发生显着变化,则召回率通常较低,并且需要重新训练。
为 HNSW 索引规划多少内存?+
数量级直接取决于 m 和索引向量的数量:除了向量本身之外,每个节点每层最多存储 m 个连接。为了可靠地估计实际数量,请在数据的代表性子集上构建索引。然后使用 pg_relation_size() 测量其大小,而不是依赖于未测量的经验法则。
我们可以使用 HNSW 索引超过 2000 个维度的嵌入吗?+
不直接在向量类型上:pgvector 拒绝在此类型上构建超过 2000 维的 HNSW 索引。解决方案是在索引创建时将列转换为 halfvec,这通过将存储精度减半来突破索引限制。这正是 Aurabase 3072 维嵌入类生产中使用的方法。

准备好部署了吗?

五分钟内完成您的后端。

无需信用卡 · 500 MB 免费 · 50,000 MAU