生产环境中pgvector在向量超过5000后检索精确率从92%骤降至68%,根因是IVFFlat索引在共享Exadata基础设施上失效,最终需重新选型Embedding模型和索引策略。
最初发表于 AIdeazz——canonical 链接在此处同步发布。
我的 RAG 生产系统构建在 Oracle Autonomous Database 之上,使用 pgvector,在超过 10,000 个向量后无法扩展。检索质量从 5,000 个向量时的 92% 精确率骤降至 10,000 个向量时的 68%。这不是理论基准测试;这是一个活跃的多代理系统,为一家航运物流客户路由客户查询,而精确率下降 24% 意味着 24% 更多的人工干预。最初 pgvector 在托管 Oracle 服务上实现经济高效 RAG 的承诺很快撞上了墙壁,迫使我重新评估嵌入模型、索引选择,并最终重新审视基础设施策略。
我们从 text-embedding-ada-002(1536 维度)开始,因为它既是默认值,也足以应对初始测试。我的 Oracle Autonomous Database(ADB)实例,即共享 Exadata 基础设施,原生提供 pgvector。搭建过程很简单:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
content TEXT NOT NULL,
embedding vector(1536)
);
CREATE INDEX ON documents USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);
我基于 100,000 向量以下数据集的一般建议,选择了 lists = 100 的 IVFFlat。初始数据集很小,大约 2,000 份内部策略文档,每份平均 500 个 token。摄入这些文档、通过 OpenAI API 生成嵌入并存储它们很简单。对于 k=5 最近邻,检索延迟始终低于 50ms。我们的代理运行在 Oracle Cloud Infrastructure(OCI)Container Instances 上,使用 langchain_pgvector 进行检索,将上下文喂给 Groq Llama 3 8B 代理进行初步处理,然后对复杂情况升级到 Claude 3 Haiku。精确率很高,约为 92%,通过对检索到的块与真实答案进行人工评估来衡量。
随着客户扩展,知识库也在增长。我们添加了更多内部 FAQ、发货清单和客户服务日志。在大约 5,000 个向量时,检索延迟开始攀升,达到 80ms。在 10,000 个向量时,延迟飙升至 250ms,精确率降至 68%。这令人无法接受。代理开始更频繁地产生幻觉,或者干脆表示找不到相关信息,导致人工干预增加。
我的 pgvector 索引是瓶颈。lists = 100 的 IVFFlat 索引表现吃力。search_list 参数默认为 lists(在我的案例中是 100),意味着每次查询它要扫描 100 个列表。在 10,000 个向量的情况下,每个列表平均包含 100 个向量。这仍然有大量的距离计算。
我尝试将 lists 增加到 200,然后是 500。
ALTER INDEX documents_embedding_idx SET (lists = 200);
REINDEX INDEX documents_embedding_idx;
这使延迟略有改善(10k 向量时降至 180ms),但没有恢复精确率。实际上,如果查询向量落入一个稀疏填充的列表,过多增加 lists 会降低精确率。权衡显而易见:IVFFlat 在我当前的配置下连这个规模都无法稳健应对。
text-embedding-ada-002 模型每 1K token 花费 $0.0001。对于 10,000 份平均 500 token 的文档,这就是 500 万 token,或 $500 的初始摄入成本。成本不算高,但当你拿的是零 VC 的天使轮时,每一分钱都很重要。更重要的是,它的性能现在已经令人质疑。
我用开源模型做了实验:bge-small-en-v1.5(384 维度)和 e5-large-v2(1024 维度)。我在 OCI VM 上使用单个 NVIDIA A10 GPU 本地运行这些模型批量生成嵌入,然后上传到 ADB。
bge-small-en-v1.5(384D):优点:嵌入生成速度快得多(本地推理),向量尺寸小得多(384 维度 vs 1536),减少存储并可能因每次距离计算的浮点运算减少而改善 pgvector 性能。缺点:10k 向量时精确率降至 60%。较小的维度根本无法捕获我特定领域文档的足够细微差别。
e5-large-v2(1024D):优点:精确率优于 bge-small-en-v1.5,在 10k 向量时达到 75%。在该规模下仍优于 ada-002 的 68%。本地推理可以接受。缺点:向量尺寸大于 bge-small,但仍小于 ada-002。延迟仍是问题,徘徊在 150ms 左右。
e5-large-v2 提供了更好的平衡,但 pgvector 性能仍是主要瓶颈。问题不仅仅在于嵌入模型,还在于检索基础设施。
IVFFlat 是一个好的起点,但对于任何超出微小规模的场景,HNSW(Hierarchical Navigable Small World)在召回率和速度方面通常更优。在 pgvector 上使用 HNSW 的挑战在于其内存占用。它是一种内存索引,意味着它消耗的 RAM 与向量数量及其维度成正比。在共享 Oracle Autonomous Database 上,我对分配给特定 pgvector 索引的内存控制有限。
我删除了 IVFFlat 索引并创建了 HNSW 索引:
DROP INDEX documents_embedding_idx;
CREATE INDEX ON documents USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 100);
m = 16:在索引构建期间为每个新元素创建的双向链接数量。m 越高意味着连接越多、召回率越高,但构建速度更慢、索引尺寸更大。
ef_construction = 100:索引构建期间最近邻的动态列表大小。ef_construction 越高意味着索引质量越好,但构建速度越慢。
使用 e5-large-v2 嵌入重建索引后,结果是立竿见影的:
延迟:降至 60ms(10k 向量时)。
精确率:恢复到 88%。
这是一个显著的改进,使我们回到了可接受的性能水平。然而,10,000 个 e5-large-v2 向量(1024 维度)的 HNSW 索引大小约为 1.5GB。这在共享 ADB 实例上是一个隐患,那里的内存资源不是专用的。我预计在接近 50,000 个向量时会触及内存限制或性能劣化,可能导致交换或索引从内存中驱逐。
Oracle Autonomous Database 对于托管关系型工作负载来说非常出色。它的自动扩展、打补丁和备份功能非常宝贵。然而,对于像带 HNSW 的 pgvector 这样的专业工作负载,"自主"特性反而成了约束。我无法直接控制:
专用内存:HNSW 依赖专用 RAM 才能发挥最佳性能。在 ADB 上,我共享资源。如果同一 Exadata 基础设施上的其他租户在大量使用他们的数据库,我的 pgvector 索引可能会获得更少的内存,导致性能下降。
向量操作的 CPU 核心:虽然 pgvector 可以利用多个核心进行距离计算,但在共享系统上,我无法直接控制分配给我特定 pgvector 查询的核心数量。
存储类型:虽然 Exadata 很快,但我无法专门为我的 pgvector 索引指定 NVMe SSD,这可以进一步减少索引查找的延迟。
这些限制意味着,虽然 Oracle ADB 上的 pgvector 对于小规模 RAG 来说很方便,但对于需要精确资源控制的高性能、高规模向量搜索来说,它不是一个长期解决方案。我目前的计划是密切监控性能,因为我们将接近 20,000 个向量。如果性能再次劣化,下一步将是将向量存储迁移到运行 PostgreSQL + pgvector 的专用 OCI VM,甚至可以是专门的向量数据库(如 Qdrant 或 Weaviate),从而完全控制硬件资源。这会引入额外的运维开销,但对于生产稳定性来说,这是一个必要的权衡。
Q:为什么不使用 Oracle 自带的向量能力而是用 pgvector?
A:Oracle Database 23ai 提供了原生向量能力,但尚未在 Autonomous Database 上正式发布。我的生产系统六个月前就需要一个解决方案,而当时 pgvector 是在 ADB 上唯一可行的选项。
Q:这个工作负载下 Oracle Autonomous Database 的确切成本是多少?
A:我的 ADB 实例最初是"永久免费"层,后来扩展到 2 个 OCPU 和 1TB 存储,费用为 $0.35/OCPU-小时。对于 10,000 个向量,数据库成本约为每月 $50,主要来自计算资源而非存储。
Q:你考虑过使用云托管向量数据库服务吗?
A:考虑过,但拿到零 VC 融资时,每一分钱都很重要。Pinecone 或 Zilliz 等服务对于我的初始规模(例如 10k 向量、1536D 每月 $70-$100)来说明显更贵,相比 pgvector on ADB 方案。我当时的目的是利用现有基础设施。
Q:你是如何测量 RAG 系统精确率的?
A:我们结合了人工评估和一个小型的、手动策划的 100 条查询测试集。对于每条查询,人工标注员对前 5 个检索块的相关性进行 3 分制评分(相关、部分相关、不相关)。精确率计算为:(相关块数量)/(检索到的总块数)。
Q:如果 HNSW on ADB 在 50k 向量时碰壁,你的计划是什么?
A:计划是将向量存储迁移到运行 PostgreSQL + pgvector 的专用 OCI VM 或专门的向量数据库(如 Qdrant)。这样可以做到专用内存和 CPU 分配,完全控制 HNSW 性能参数和扩展。
— Elena Revicheva · AIdeazz · Portfolio