news 2026/10/6 8:56:40

pgvector+PostgreSQL构建RAG知识库实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
pgvector+PostgreSQL构建RAG知识库实战指南

如果你手头已经跑着一套 PostgreSQL,又想做语义搜索、搭一个 RAG 知识库,但不想为了向量检索再引三套中间件,那 pgvector 几乎是绕不开的选择。它是 PostgreSQL 官方的向量检索扩展,直接把 embedding 存进数据库,用 SQL 就能做相似度搜索,还能和你的业务数据 JOIN、一起做事务、一起做备份。这篇指南我会从安装配置、建表索引、语义搜索查询,到完整的 RAG 流水线,一步步讲清楚,也把我在实际项目中踩过的坑和调优经验一并分享出来。适合已经熟悉 PostgreSQL 但没接触过向量检索的开发者,也适合正在做 RAG 知识库、但被向量数据库选型困扰的朋友。

1. 为什么是 pgvector:语义搜索到底在解决什么问题

1.1 关键词搜索的边界在哪里

传统搜索方案,不管是 SQL 里的LIKE '%关键词%',还是 PostgreSQL 的全文检索tsvector,本质都在做字面匹配。你能搜到“包含这些词”的文档,但搜不到“意思相近但没有任何一个词相同”的内容。比如用户问“笔记本没电了怎么办”,词面匹配要求文档里出现“笔记本”“没电”这些字样,可如果文档标题是“电脑电池耗尽后的应急处理”,传统搜索就彻底失联了。

语义搜索的思路完全不同。它先把文本扔进一个 embedding 模型,模型把这句话转换成一串几百维的浮点数向量,这个向量可以理解为“这句话在语义空间里的坐标”。语义相近的两句话,向量在空间里的距离就近;语义无关的,距离就远。搜索的时候,只需要把用户的查询也转成向量,然后在库里找“离它最近”的那些向量对应的文档,就实现了真正意义上的“按意思搜”。

这里我用一个生活化类比帮新手理解:关键词搜索像你按门牌号找地址,必须知道确切的门牌;语义搜索像拿着一张照片去问路人“这个地方在哪”,对方看的是整体环境和特征,不需要你说的每个字都和路牌对上。

1.2 三种常见向量数据库方案的取舍

做语义搜索第一反应可能是上独立向量数据库,比如 FAISS、Milvus、Qdrant 这些。它们确实性能强悍,但代价也很实在:多了一套分布式系统要部署、要监控、要保证高可用;数据和 PostgreSQL 之间要做同步,经常面临双写一致性问题——业务库更新了,向量库里还是旧数据;事务也没法跨系统保证。对于中小团队、内部工具、个人项目来说,这个运维负担往往比搜索引擎本身还重。

pgvector 走的是另一条路线:不额外引入任何组件,就在 PostgreSQL 内部新增一种vector数据类型和对应的索引方法。你可以在同一个事务里同时更新业务表和向量表,可以用一条 SQL 完成“筛选条件 + 语义排序”,可以继续用 PostgreSQL 的权限体系、备份恢复、扩展生态。

方案部署成本数据一致性适合场景
FAISS / Milvus / Qdrant独立服务,需部署维护需自行同步,易不一致千万级以上向量、延迟极敏感的大型系统
pgvector安装扩展即可与业务数据同库同事务百万级以下向量、中小项目、需要和业务数据 JOIN

我这里说的百万级是个经验边界,不是硬性上限。pgvector 在海量数据下也能用,但独立向量库在超大规模、超高 QPS 场景下确实有更成熟的分布式方案。选型时关键是别一开始就追求“极致性能”,多数项目的数据量连 100 万向量都不到,pgvector 在百万级上跑 HNSW 索引的查询时延通常在几十毫秒级别,完全够用。

1.3 pgvector 的工作原理:距离函数与向量索引

使用 pgvector 之前,至少要知道三个距离函数:<->表示欧氏距离(L2),<=>表示余弦距离,<#>表示负内积。文本语义搜索最常用的是余弦距离,因为它的计算只关心向量的方向,不关心向量长度,这正好符合 embedding 模型输出的特性——模型更在意语义方向而不是绝对数值。

原始数据量一大,全表扫描逐个算距离是灾难。pgvector 提供了两种索引:IVFFlat 和 HNSW。IVFFlat 的思路是先对向量空间做聚类分桶,查询时只挑最近的几个桶搜索,有点像图书馆先按大类分区再找书;HNSW 的思路是构建一个多层近邻图,查询时从最上层往下逐层逼近,有点像社交网络里“找朋友的朋友”的六度分隔。HNSW 的查询精度和速度普遍优于 IVFFlat,构建速度稍慢但可接受,新项目基本可以直接选 HNSW。

2. 环境准备:PostgreSQL 版本选择与 pgvector 安装

2.1 版本怎么选:14 是底线,16/17 更省心

pgvector 对 PostgreSQL 的版本有下限要求。HNSW 索引需要 PostgreSQL 14 及以上版本,所以如果你还在用 12、13,建议先升级数据库,别急着装扩展。当前主流发行版默认提供 PostgreSQL 16 或 17,功能稳定,社区资料也多,新项目直接选这两个版本就好。

还有一点容易被忽略:如果你打算用源码编译安装 pgvector,需要先装好 PostgreSQL 的开发头文件,在 Debian/Ubuntu 上是postgresql-server-dev-16这个包,Red Hat/CentOS 系是postgresql16-devel。缺了头文件,make会直接报错找不到pg_config。实际工作中不少人的安装失败就是卡在这一步。

2.2 三种安装方式,按你的环境挑一种

我按从省事到折腾的顺序排一下:

  • 包管理器安装:Debian/Ubuntu 上apt install postgresql-16-pgvector,Fedora 上dnf install postgresql16-pgvector。装完就完了,不需要编译,最省心。
  • 源码编译安装:从 GitHub 拉取 pgvector 源码,执行make && make install。这个方式适合没有现成软件包的环境,或者你想用最新特性。注意编译前确认pg_config在你的PATH里,而且它指向的目标 PostgreSQL 版本和你当前运行的服务一致。如果你机器上有多个 PostgreSQL 版本,这一步最容易掉坑。
  • Docker 安装:官方镜像pgvector/pgvector:pg16或者pgvector/pgvector:pg17已经把扩展编译好了,直接拉起来用。如果你用的是标准postgres镜像,也可以自己写个 Dockerfile 额外安装,本质是复制编译产物。我个人的建议是:能用官方现成镜像就用现成的,少踩编译的坑。

2.3 验证安装:别急着写代码,先花一分钟确认扩展可用

装好之后,连到数据库里执行:

CREATE EXTENSION IF NOT EXISTS vector;

看到CREATE EXTENSION的返回就说明成功了。再跑一句SELECT * FROM pg_available_extensions WHERE name = 'vector';可以确认扩展版本。如果报错extension "vector" is not available,大概率是扩展文件装到了别的 PostgreSQL 实例目录下,或者安装路径的版本和你当前连接的数据库版本不一致。注意,装 pgvector 不需要设置shared_preload_libraries,它不像某些扩展需要预加载到共享内存里。

我踩过的一次坑是:用源码编译时没注意pg_config指向的是 PostgreSQL 15,而实际跑了两个实例,一个 15 一个 16,结果扩展装错地方了。排查方法很简单,psql里执行select version();确认当前实例版本,再执行select current_setting('server_version');对比一下,如果环境允许,直接在对应版本的bin目录下重新编译一次最省事。

3. 建表、向量化与索引:让数据变成可检索的向量

3.1 表结构设计:别把所有东西塞进一个大字段

我建议用两张表来组织 RAG 知识库的数据。第一张是文档表,记录原始文档的元信息;第二张是分块表,记录切分后的文本块和对应的向量。这样设计的好处是,后续做文档更新、权限过滤、来源追踪都方便,也符合 RAG 检索的粒度——搜索是对“文本块”做的,不是对整个文档做的。

CREATE TABLE documents ( id BIGSERIAL PRIMARY KEY, title TEXT NOT NULL, source TEXT, created_at TIMESTAMPTZ DEFAULT now() ); CREATE TABLE document_chunks ( id BIGSERIAL PRIMARY KEY, document_id BIGINT REFERENCES documents(id) ON DELETE CASCADE, chunk_index INT NOT NULL, content TEXT NOT NULL, embedding vector(1024) );

embedding字段的维度必须和你的 embedding 模型输出维度严格一致。如果你用 OpenAI 的text-embedding-3-small,维度是 1536;用text-embedding-3-large,维度是 3072;用本地模型 BGE-M3,维度是 1024。这块一旦建表时定错了,后续插入向量会直接报错,所以开工前一定要先确认模型输出维度。另外,我把metadata(比如文档分类、权限标签、URL 链接)放在了文档表里,检索时可以关联回来做过滤,比塞进 JSON 字段里管理起来更清晰。

3.2 生成 embedding 的两种主流路径

生成 embedding 是整个链路里最外部的环节,但也是最影响检索效果的一环。这里我给两条路径。

路径一:本地模型,数据不出内网。用 Ollama 跑一个 BGE-M3 或者其他 embedding 模型,然后通过 HTTP 接口调用。这是我自己现在最推荐的做法,尤其适合企业内部知识库,文档往往涉及敏感信息,调外部 API 心里没底。启动一个本地模型后,调用方式很简单:

curl http://localhost:11434/api/embed \ -H "Content-Type: application/json" \ -d '{"model": "bge-m3", "input": "笔记本没电了怎么办"}'

模型会返回一个 1024 维的 float 数组,这个数组就是你插入数据库的embedding值。

路径二:调用 OpenAI 或其他云端 embedding API。如果你的场景允许数据出网,并且团队已经有现成的 API Key,用text-embedding-3-small也能获得不错的效果。调用方式用官方 SDK 或者requests都行。要注意的是,云端 API 有速率限制和费用,批量入库时最好做一下重试与限速。

无论哪条路径,嵌入的质量直接决定语义搜索的上限。我个人建议大家优先选中文效果好的模型,BGE 系列的向量化模型在这块做得比较稳。模型选完之后,把一整批数据向量化插入库里的脚本大致长这样:

import psycopg2 import requests conn = psycopg2.connect("host=localhost dbname=mydb user=postgres") cur = conn.cursor() texts = ["文档一的文本内容", "文档二的文本内容"] for doc_id, text in enumerate(texts, start=1): resp = requests.post("http://localhost:11434/api/embed", json={"model": "bge-m3", "input": text}).json() embedding = resp["embeddings"][0] cur.execute( "INSERT INTO document_chunks (document_id, chunk_index, content, embedding) VALUES (%s, %s, %s, %s)", (doc_id, 0, text, embedding) ) conn.commit()

有一点必须强调:插入的 Python 列表会被 psycopg2 自动转换成 PostgreSQL 的数组,但 pgvector 存的是vector类型,严格来说需要显式类型转换。实际使用中,你可以直接传字符串形式的'[0.1,0.2,...]',让 PostgreSQL 隐式转换,或者用psycopg2.extras注册适配器,否则会报column "embedding" is of type vector but expression is of type double precision[]之类的类型错误。这个坑我见过至少三次,新手最容易在这卡住。

3.3 HNSW 与 IVFFlat 的关键参数:谁适合你的数据量

索引创建语法很简单,但参数选择直接影响查询速度和精度。先说结论:新项目、数据量在几万到几百万之间,直接上 HNSW。

CREATE INDEX ON document_chunks USING hnsw (embedding vector_cosine_ops);

HNSW 有两个构建参数:m控制每个节点的最大连接数,默认 16,调大到 32 可以提高召回率,但会使索引更大、构建更慢;ef_construction控制构建时的动态列表大小,默认 64,调大到 128 能提升索引质量,同样牺牲构建速度。查询时还有一个会话级参数hnsw.ef_search,控制搜索时考察的候选节点数量,默认 40,调到 100 左右能明显提升召回,但查询延迟也会上升。

IVFFlat 的话,参数是lists和probes。lists表示分成多少个聚类桶,一般建议行数除以 1000,比如 50 万行就设 500;probes是查询时搜索几个桶,默认 1,调到 10 左右能提升召回。注意,IVFFlat 有个先决条件:索引建好后必须先有数据,否则聚类结果是空的,而且数据如果分布变化太大,索引质量会下降。

说实话,2024 年之后的新项目我是无脑推荐 HNSW 的,它的查询稳定性比 IVFFlat 好太多,参数也不用调来调去。

4. 从向量到语义搜索:查询写法与混合检索

4.1 最基础的语义搜索 SQL:一行代码实现“按意思找”

假设用户输了一个问题,你先把它转成向量,然后执行查询:

SELECT id, content, 1 - (embedding <=> '[0.1, 0.2, ...]') AS similarity FROM document_chunks ORDER BY embedding <=> '[0.1, 0.2, ...]' LIMIT 5;

这里<=>是余弦距离,返回 0 表示完全一致,1 表示完全无关,2 表示方向完全相反。为了直观展示相关度,我用1 - 距离把它转换成相似度分数。实际项目里我们经常在应用层生成查询向量,然后通过参数化查询传入,避免每次拼 SQL。

一个常见疑问是:为什么排序用<=>而不是<->。取决于你 embedding 模型的训练方式。模型如果做了归一化——所有向量长度都是 1——那么余弦距离、欧氏距离、内积在排序意义上是一致的;但有些模型没做归一化,这时余弦距离更稳定,因为它只看方向不管长度。我常用的 BGE-M3 输出已经是归一化的,但为了通用性,文本场景我仍然建议用<=>。

4.2 带条件过滤的向量检索:WHERE 子句与索引的相爱相杀

真实业务不会只做全局语义搜索,总要加一些过滤条件,比如“只看技术类文档”“只看某个月的数据”。SQL 写起来很直接:

SELECT id, content, 1 - (embedding <=> $1) AS similarity FROM document_chunks WHERE document_id IN (SELECT id FROM documents WHERE category = '技术文档') ORDER BY embedding <=> $1 LIMIT 5;

但这里藏着一个性能问题:HNSW 索引本质上是先找“全局最近邻”,再在结果集里过滤。如果过滤条件很强——比如只保留了 1% 的数据——索引可能选出来的邻居大部分都被过滤掉了,导致召回不满 5 条或者结果不准确。面对这个场景,我的经验是:如果过滤后数据量仍然比较大(几万条以上),可以直接在查询时加一个显式的WHERE条件,让 PostgreSQL 先做一个粗筛,再排向量;如果过滤后数据量很小,这种写法完全没问题。极端情况下,可以考虑建部分索引,例如只对某个分类的文档建 HNSW 索引。

pgvector在 0.7.0 之后对WHERE过滤和 HNSW 的配合有所优化,但如果你的过滤维度很多,还是建议在应用层做两层结构:先根据条件缩小候选 ID 集合,再对候选集合做向量搜索。

4.3 混合检索:全文检索 + 语义向量,两个都要

只做语义搜索会有一个尴尬场景:用户问“请帮我找编号 DOC-2024-001 的文档”,这个编号在语义空间里没有任何意义,纯向量搜索大概率翻车。这时候必须靠全文检索兜底。PostgreSQL 自带的tsvector全文搜索对精确词、编号、专业名词非常擅长,两者配合才是一个完整的检索系统。

实践中我一般这样合并:

SELECT id, content, ts_rank(to_tsvector('simple', content), plainto_tsquery('simple', 'DOC-2024-001')) AS text_score, 1 - (embedding <=> $1) AS semantic_score FROM document_chunks WHERE to_tsvector('simple', content) @@ plainto_tsquery('simple', 'DOC-2024-001') OR 1 - (embedding <=> $1) > 0.7 ORDER BY (text_score + semantic_score) DESC LIMIT 5;

注意我用了simple配置而不是默认的english或chinese,因为默认分词对中文不友好,对编号这种“词”反而会拆得乱七八糟。至于text_score和semantic_score的权重怎么配,没有标准答案,我的做法是先全跑一遍,看哪些查询靠语义命中、哪些靠全文命中,然后给全文检索一个小的降权系数。这个比例值得你在自己的数据集上花时间做实验,它是区分“能用”和“好用”的关键一步。

5. 把搜索变成问答:构建一条可用的 RAG 流水线

5.1 RAG 的基本形态与适用场景

RAG(Retrieval-Augmented Generation,检索增强生成)说白了就是:先从知识库里检索出相关文档片段,再把片段拼进 Prompt,最后让大模型基于这些片段回答。它解决的痛点是 LLM 没有你的私有数据、会一本正经地胡编、知识版本停留在训练时刻。用 RAG 把内部文档、FAQ、售后记录喂给模型,它就能像“带着资料开卷考试”一样回答你的业务问题。

适合 RAG 的场景包括:企业内部知识库问答、电商智能客服、文档搜索引擎、医疗/法律等行业的专业问答助手。判断你的场景适不适合 RAG,一个简单的标准是:答案是否存在于你们已有的文档里。如果是,RAG 大概率有效;如果答案需要基于多份文档推理、综合判断,RAG 也能帮上忙,但你需要调优策略。

5.2 文档切分的实操细节:chunk size 和 overlap 不是玄学

很多人在 RAG 里效果差,问题不在向量数据库,而在数据进入数据库之前的切分环节。切分太粗,每个 chunk 包含太多主题,向量平均化之后语义模糊;切分太细,一个完整知识被拆散,检索时上下文不足。我自己的经验法则:

  • 按语义单元切分:优先按 Markdown 标题、段落、列表等结构边界切,而不是无脑按字符数硬切。结构边界天然是语义边界。没有结构时再按长度切。
  • chunk size 控制在 300-500 个汉字左右。OpenAI 的 tokenizer 大概是 1 个汉字 ≈ 1.5-2 token,500 汉字 ≈ 750-1000 token。太大吞细节,太小丢上下文。
  • overlap 设置在 50-100 字。overlap 的作用是避免一句话恰好被一刀切开,导致语义断掉。它不是越多越好,越多冗余越大、索引越大、检索时噪声越高。

如果你用的是 LangChain,可以这么配:

from langchain_text_splitters import RecursiveCharacterTextSplitter splitter = RecursiveCharacterTextSplitter( chunk_size=500, chunk_overlap=80, separators=["\n\n", "\n", "。", "!", "?", ".", " "], )

上面这个separators顺序是我调出来的,中文用句号、感叹号、问号作为兜底边界,比默认的纯英文标点靠谱很多。Java 生态的话,LangChain4j 里有一个Easy RAG模块,封装了文档解析、切分、向量化入库和检索问答,连 pgvector 的接口都直接接好了,用起来省不少事。

切分完的 chunk 顺序要保留,chunk_index字段就是干这个用的,后续如果要做多 chunk 上下文拼接或者引用溯源,都靠它。

5.3 从检索到生成:完整的最小 Python 实现

整个 RAG 链路不需要引入重框架,用psycopg2做检索、用requests调模型,三十行代码就能跑通。我把一个最小实现贴出来,这个版本已经是我在实际项目中跑过、可以用于小规模内部工具的骨架:

import psycopg2 import requests def get_embedding(text): resp = requests.post("http://localhost:11434/api/embed", json={"model": "bge-m3", "input": text}) return resp.json()["embeddings"][0] def search(query, top_k=5): vec = get_embedding(query) conn = psycopg2.connect("host=localhost dbname=mydb user=postgres") cur = conn.cursor() cur.execute( """ SELECT content, 1 - (embedding <=> %s::vector) AS similarity FROM document_chunks ORDER BY embedding <=> %s::vector LIMIT %s """, (vec, vec, top_k) ) results = cur.fetchall() cur.close() conn.close() return results def ask(query): results = search(query) context = "\n\n".join([r[0] for r in results]) prompt = f"""你是一个企业内部助手。请严格根据下面的资料回答问题。 如果资料中没有相关信息,请直接说“资料中未找到相关信息”,不要编造。 资料: {context} 问题:{query} """ resp = requests.post("http://localhost:11434/api/chat", json={"model": "qwen2.5", "messages": [{"role": "user", "content": prompt}]}) return resp.json()["message"]["content"] print(ask("笔记本没电了怎么办"))

这里面有个细节:%s::vector是必要的显式类型转换,否则参数推断有时会出问题。top_k我一般设 5,太多会带进噪声,太少上下文不够。要注意的是,ask的模型(qwen2.5)和get_embedding用的模型(bge-m3)是两个不同的模型,前者管生成,后者管向量化,这条链路你一定要分开看,不然很容易混淆。

5.4 RAG 的瓶颈与优化方向:为什么说七成功夫在检索

很多人做 RAG 时把精力全花在调 Prompt、换大模型上,结果效果依然不稳定。我做了几轮之后才意识到:RAG 的上限由检索决定,生成只是把检索到的知识组织成通顺的语言。检索如果召回不到正确答案,后面换再强的模型也是白搭。

RAG 的瓶颈有几层。第一层是召回率:相关文档根本没被搜出来,再强的生成也没用。优化方向包括调 HNSW 参数、混合检索、rerank。第二层是噪声率:检索结果里混入太多不相关内容,干扰模型判断。优化方向是把 chunk 切得更干净,加强元数据过滤。第三层是评估:没有量化指标,你就不知道怎么优化。我建议至少记录两个数字:命中率(正确答案是否出现在检索返回的 top-5 里)和生成准确率(最终回答是否让用户满意)。先跑一个 50 条问题的测试集,每次改动都跑一遍,用数字说话。

Rerank 这个词值得展开。第一轮向量检索返回 20 条候选,然后用一个专门的重排模型(比如 BGE-Reranker)对这些候选逐条和查询算相关度分数,重新排序后只取前 5 条。这个动作能在不太增加延迟的情况下显著提升效果,是目前很多产品级 RAG 的标准做法。不过它属于锦上添花,新手先把基础链路跑通、把数据切好、索引建对,效果已经能覆盖大部分需求了。

6. 常见问题与避坑实录

6.1 向量查询慢、没走索引,怎么办

先用EXPLAIN ANALYZE看执行计划里有没有Index Scan using document_chunks_embedding_idx,如果看到Seq Scan说明全表扫描了。常见原因有三个:没建索引(最蠢但也最常见);查询里LIMIT太大,走了索引还要回表太多条,规划器认为全表扫更快;过滤条件导致索引不能有效利用。HNSW 索引的ef_search也可以适当调大,默认 40 对精度要求高的场景偏低,我可以承受查询慢 10 毫秒换召回提升,通常就会先调它试试。

6.2 RAG 知识库能存图片吗

很多人问“RAG 知识库能存储图片吗”,答案是可以,但你要搞清楚存的是什么。纯文本向量库存不了图片内容,但你可以用视觉语言模型(比如 CLIP 或者 Qwen-VL)把图片转成视觉向量,存进 pgvector 里,然后支持“用文字描述找图片”的语义检索。更常见的做法是:图片本身存到对象存储或者bytea字段里,图片生成的文字描述向量化后进向量库,检索到描述再带出图片 URL。所以严格说,pgvector 存的是图片的可搜索特征,不是图片本身。视觉向量和文本向量是两个空间,不要混在一起插进同一个向量字段。

6.3 中文语义搜索效果差,问题通常不在数据库

中文检索效果差,先别怀疑 pgvector,99% 的情况是 embedding 模型和切分策略的问题。通用英文模型对中文的支持参差不齐,我强烈建议中文场景直接用 BGE-M3 这样的国产中文向量模型。另外,中文没有天然空格分词,切分时如果不按句子边界切,很容易把一个完整语义切成碎片。我之前遇到一个案例,某字段内容都是“技术支持电话:400-xxx-xxxx”,切分时正好从中间切断,导致检索命中率下降,后来加了句号兜底和 overlap 才解决。

6.4 向量索引膨胀与数据更新维护

业务数据频繁更新删除,会导致 HNSW 索引膨胀,查询性能下降。PostgreSQL 的索引膨胀在向量索引上同样存在,我的维护习惯是:每天增量导入后,如果删除量超过了总量的 10%,就执行一次REINDEX INDEX document_chunks_embedding_idx。这操作会锁表,建议放在低峰期执行。另外,批量导入时先删除索引、导入完再重建,比边导边维护快得多,这个思路和普通 PostgreSQL 索引优化完全一样。

6.5 常见问题速查表

现象可能原因排查/解决
CREATE EXTENSION报错扩展装到了其他版本的实例目录确认pg_config指向的版本,重新编译安装
插入向量时类型错误没有做类型转换SQL 里显式%s::vector
查询不走向量索引没建索引 / 过滤条件过强EXPLAIN ANALYZE查看计划,调ef_search
中文效果差embedding 模型选型或切块问题换 BGE 系列模型,调整separators和 overlap
检索结果相关但噪声多chunk 太大或 top_k 太大缩小 chunk_size,降低 top_k,加 rerank
索引膨胀导致变慢频繁增删低峰期REINDEX

说起来,我最早做语义搜索的时候,第一反应是上 FAISS,后来发现数据要从业务库导出、转换、同步,维护成本极高,迁移到 pgvector 之后只用了一张表就搞定了整个内部知识库的检索。如果你的数据量在百万级以下,pgvector 的体验真的非常顺滑,尤其是和既有 PostgreSQL 业务数据做 JOIN、做权限过滤的时候,那种“自带数据库原生气质”的优势,是独立向量库给不了的。如果你正在纠结要不要为了 RAG 上一个新数据库,我个人的建议是先在自己的 PostgreSQL 实例上把 pgvector 跑起来,用最小闭环验证整个效果链路,数据规模真到了千万级、性能指标确实追不上的时候,再考虑迁移到独立向量数据库也不迟。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 8:56:40

剑侠情缘源码技术拆解:地图编辑器与老RPG架构解析

说实话&#xff0c;看到【180609】剑侠情缘_整套源码地图编辑器(单机学习例子)这个打包名的时候&#xff0c;我第一反应是有点感慨。这类资源在老玩家的硬盘里其实很常见&#xff0c;一个压缩包把代码、工具、资源一股脑塞进去&#xff0c;标注成“学习例子”。但真正能静下心来…

作者头像 李华
网站建设 2026/10/6 8:56:07

云和恩墨与YashanDB联手:国产数据库一体机的技术落地与选型指南

这消息刚在圈子里传开时&#xff0c;我手机上的DBA群就热闹了一阵。有人问云和恩墨和YashanDB搭伙做国产数据库一体机&#xff0c;到底图什么&#xff1b;也有人在讨论这种组合和过去那些“服务器厂商贴个数据库标签”的一体机有什么区别。我的第一反应倒不是参数和跑分&#x…

作者头像 李华
网站建设 2026/10/6 8:54:50

区域地下水位预测实战:GCN-LSTM 多井时空建模与避坑指南

简介&#xff1a;这份资源面向环境科学专业学生、水务工程技术人员及相关领域研究人员&#xff0c;提供一套融合图卷积网络与长短期记忆网络的区域级多井地下水位时空预测方案&#xff0c;用于解决多井空间分布差异大、水位关联性强条件下的同步预测难题。压缩包内共1个PDF文件…

作者头像 李华
网站建设 2026/10/6 8:54:00

openGauss 2025前瞻:AI原生、存储过程与生态迁移的破局之路

1. 数智时代的数据库"分水岭"&#xff1a;为什么所有人都在等这场发布 数据库选型这件事&#xff0c;我最近半年被问到最多的一个问题是&#xff1a;openGauss到底能不能扛核心系统&#xff1f;问的人里有做金融的、做政务的、做能源的&#xff0c;也有互联网公司想省…

作者头像 李华
网站建设 2026/10/6 8:51:46

时间处理核心指南:时间戳、时区与分布式时钟全解析

1. 时间戳与Epoch&#xff1a;一切时间的基准聊时间概念&#xff0c;绕不开的第一个东西就是时间戳。不管你写后端接口、做日志分析、设计数据库表&#xff0c;还是调一个第三方API&#xff0c;时间戳几乎是所有时间体系的锚点。我先把最基础的逻辑理清楚&#xff0c;后面那些复…

作者头像 李华
网站建设 2026/10/6 8:51:28

Redis集群哈希槽机制详解:从CRC16原理到槽迁移实战

聊到Redis集群&#xff0c;绕不开“哈希槽”这个词。面试官只要问到集群数据分布&#xff0c;十有八九会抛出一句&#xff1a;“你先说说哈希槽是怎么算的&#xff1f;”如果只能答出“CRC16取模”&#xff0c;那基本属于送分没接住。我在实际搭建和维护Redis Cluster的几年里&…

作者头像 李华