上周要在一台 Windows 笔记本上把本地语义搜索的 Demo 跑起来,整个方案里最让我头疼的不是模型 inference,而是几百条文本 embedding 完之后往哪儿放。单独搭一个向量数据库太绕,数据同步、运维、备份全要操心,最后我还是选了 PostgreSQL 加 pgvector 扩展——不引入额外服务,SQL 照常用,业务数据和向量放进同一个库。这篇文章就把我在 Windows 上安装 PostgreSQL 和 pgvector 的完整过程写清楚,从下载安装器一直写到跑通一条向量检索查询,适合所有想在本地环境快速验证向量检索方案、又不想碰 Linux 的开发者。
1. 它不是独立数据库:先用一分钟搞懂 pgvector 的定位
先把这个概念掰开:pgvector 不是一个独立数据库,而是 PostgreSQL 的一个扩展(extension)。它做的事情通俗讲就是给 PostgreSQL 塞进一个全新的vector类型,再配套一套距离运算符和索引方法,让数据库原生支持向量的存取和相似度查询。
很多人第一次接触向量检索时,第一反应是去用 Milvus、Chroma、Weaviate 这类专门产品。这些工具当然有自己的优势,但如果你手头已经有一个 PostgreSQL 实例,或者你只是想在本地做原型验证,pgvector 反而是更轻的选择。我列个表直观对比一下:
| 对比项 | pgvector | 独立向量数据库 |
|---|---|---|
| 部署复杂度 | 安装扩展,随 PG 起停 | 独立服务,需要额外运维 |
| 数据一致性 | 和业务表同库同事务 | 往往需要自己处理同步 |
| 查询生态 | 直接写 SQL 就能查 | 通常要学一套 API |
| 适用规模 | 百万级以内很舒服 | 海量数据、分布式需要 |
| 运维成本 | 几乎为零 | 内存、副本、监控都要管 |
我的判断标准很简单:数据量没到百万以上、不想多养一个服务、想要 SQL 的灵活性和事务能力,pgvector 就是性价比最高的答案。它不是什么银弹,但把“语义搜索、RAG、推荐召回”这类需求塞进传统业务系统里,几乎是无痛的。
从实现原理上看,pgvector 的定位其实很清晰:它底层的核心是 C 语言实现的自定义类型和运算符,数据格式使用 PostgreSQL 的 varlena 变长存储机制,0.7.0 版本之后单条向量最大支持 16000 维;查询时通过<->(欧氏距离)、<=>(余弦距离)、<#>(负内积)三个运算符完成相似度计算;索引层面提供 IVFFlat 和 HNSW 两种结构加速检索。理解这些之后,Windows 安装过程中很多看似奇怪的问题就变得顺理成章了——本质上你要做的,就是把这个 C 扩展编译出来的 DLL 和其他元数据文件,放到 PostgreSQL 指定目录里,让数据库引擎能加载它。
2. 安装之前,先把这三件事定下来
Windows 上装东西最怕的就是版本踩雷。我开始之前也吃过亏,所以这次把选型阶段单独拎出来说。
第一件事是选 PostgreSQL 版本。官方 Windows 安装包主要靠 EDB 提供的安装器,下载页面在 PostgreSQL 官网的 Windows 板块。目前稳定版已经到 17 甚至 18 了,但我不建议盲目追新,尤其是你要跑生产相关项目的话,选最近的大版本里比较成熟的次版本更稳妥。该教程以 16 或 17 为例,整体流程一致,不影响操作。
第二件事是 pgvector 版本和 PostgreSQL 版本的匹配关系。pgvector 的 GitHub Releases 页面里,每个 release 都会标明支持哪些 PostgreSQL 大版本。实际上单看大版本匹配就够,比如 PostgreSQL 16 对应编译好的扩展,不能直接拿去给 PostgreSQL 17 用,因为扩展本质是绑在数据库引擎里的 C 代码,ABI 必须对齐。这个坑在后面第 5 章会详细展开。
第三件事是判断你到底需不需要装 Visual Studio。很多人一开始没意识到:Windows 下安装 pgvector 不像 Linux 那样跑make && make install就完事,因为 Windows 没有自带 GNU 工具链。不过如果你运气好,下载到的 pgvector 版本刚好带了 Windows 预编译二进制,那就只需拷贝文件,Visual Studio 可以完全不碰。如果没带,那就得预备 Visual Studio 2022 Community(免费版够用),安装时勾选“使用 C++ 的桌面开发”工作负载。建议先把这一步想清楚,别等装到一半发现编译器没有,又回头下载几个 G 的 IDE,心态容易崩。
顺便把安装目录、端口、账号密码这三样也提前规划好:PostgreSQL 默认数据目录是C:\Program Files\PostgreSQL\17\data,服务端口默认 5432,超级用户是postgres,密码安装时自己设置。如果你本机 5432 已经被别的服务占了,安装时可以改端口,但后面连接工具、配置全都要跟着改,建议没特殊需求就别动,省事。
3. 一步步装好 PostgreSQL:安装器里容易忽略的细节
EDB 安装器整体上是“下一步下一步”风格,但它有几处细节,选错了后续会很难受。
打开下载好的 exe,第一步选择安装目录,默认在C:\Program Files\PostgreSQL\17。然后进入组件选择。默认全选包含 PostgreSQL Server、pgAdmin 4、Stack Builder 和 Command Line Tools。如果你只想要一个能用 psql 连的数据库,至少保留 PostgreSQL Server 和 Command Line Tools。pgAdmin 4 是图形化管理工具,新手建议勾上,查数据和跑 SQL 都方便。Stack Builder 是装插件和工具用的,用不上可以不装,省得占空间。
接下来设置数据目录和超级用户密码。数据目录默认放在 PostgreSQL 安装目录下面,也就是系统盘 Program Files 里。这里有个 Windows 特有的权限问题:Program Files 目录普通用户没有写权限,而 PostgreSQL 的数据目录又必须允许服务账户读写。安装器会自动配置好权限和服务账户,如果你手动改目录,一定要避开需要额外提权的位置。密码要设置得复杂一点,并且一定记下来。这个密码就是postgres超级用户的密码,后面所有管理操作都靠它。
端口默认 5432。如果你之前装过 MySQL,可能第一反应是“要不要换个端口防止冲突”,其实 MySQL 默认 3306,和 5432 完全不冲突,保持默认即可。语言区域设置我一般保持系统默认,但如果你打算存中文数据并且后续用 psql 导入,可以把 locale 设置成 Chinese (Simplified)_China.936,不设问题也不大,因为 PostgreSQL 内部用 UTF-8 编码,基本能覆盖中文场景。
安装到最后一步,安装器会询问是否启动 Stack Builder,这个可以取消。装完之后最重要的一件事:手动把 PostgreSQL 的 bin 目录加进系统 PATH。EDB 安装器默认不帮你加,这导致很多新手打开 cmd 敲psql显示“不是内部或外部命令”,还以为是安装失败。操作方式是在 PowerShell 里执行:
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\Program Files\PostgreSQL\17\bin", "User")设置完重新开一个终端,然后通过命令行验证服务状态:
Get-Service *postgres*正常情况下能看到一个名字类似postgresql-x64-17的服务,状态是 Running。再用 psql 登录:
psql -U postgres -h localhost -p 5432输入安装时设置的密码,能进入postgres=#提示符,说明数据库本体已经装好了。容器和 Docker 用户可能觉得装个数据库没必要这么麻烦,但 Windows 原生服务的好处是开机自启、稳定、不占额外虚拟化资源,本地开发足够用。
4. pgvector 落地:两条路线和文件去向
PostgreSQL 装好之后,接下来就是把 pgvector 扩展弄进去。这一步是 Windows 用户最难受的地方,也是网上问得最多的。先说清楚最终目标:pgvector 的安装结果实质上就是三类文件:
- 一个编译好的动态链接库
vector.dll,要放到C:\Program Files\PostgreSQL\17\lib - 一个控制文件
vector.control,要放到C:\Program Files\PostgreSQL\17\share\extension - 一个或多个版本 SQL 脚本,比如
vector--0.7.4.sql,同样放到C:\Program Files\PostgreSQL\17\share\extension
只要这三个文件各就各位,CREATE EXTENSION vector才有可能成功。理解了目标,剩下的问题就变成“这三类文件从哪来”。
4.1 路线一:官方 Release 预编译包直接拷贝
到 pgvector 的 GitHub Releases 页面,展开最新 release 的 Assets 列表。有些版本会附带 Windows 构建产物,文件名通常带 win、windows 或者 x64 字样,比如pgvector-0.7.4-windows-x64.zip一类。如果有,直接下载,解压之后你会看到 bin、lib、share 之类的目录结构,按前面的目标位置把文件拷贝过去就行。
这条路最省事,不用碰编译器,全程十分钟以内完成。但要注意:不是每个版本都保证提供 Windows 预编译包,也不保证覆盖所有 PostgreSQL 大版本。遇到没有现成包的情况,就老老实实走源码编译。
4.2 路线二:Visual Studio 源码编译
先到 GitHub 下载源码包,解压到本地目录,比如D:\pgvector-0.7.4。然后打开 “x64 Native Tools Command Prompt for VS 2022”。这一步很多人会犯迷糊:为什么必须用这个特定的命令行窗口?因为普通 cmd 里没有 MSVC 的编译环境和环境变量,nmake 根本跑不起来。这个专用命令行工具会自动帮你把 cl.exe、nmake.exe、link.exe 这些工具链全部配好,并且是 x64 架构。
打开之后,先确认pg_config能被找到:
where pg_config如果提示找不到,说明前面第 3 章的 PATH 没配置好,自己去加或者临时指定:
set PATH=C:\Program Files\PostgreSQL\17\bin;%PATH%接着进入源码目录,执行:
nmake /F Makefile.win nmake /F Makefile.win install第一条命令负责编译,第二条负责安装。安装步骤会把vector.dll、vector.control和 SQL 文件自动复制到 PostgreSQL 对应的lib和share/extension目录。注意整个窗口要以管理员身份运行,否则向C:\Program Files\PostgreSQL\17下写入文件时会提示权限不足。
编译期间常见的报错有两种。一种是找不到libpq-fe.h之类的头文件,这种通常是 PATH 里 PostgreSQL 路径没配好,或者 VS 用的是 32 位工具链,确认你打开的是 x64 版本即可。另一种是编译到一半提示nmake不是内部命令,说明你开的是普通 cmd 而不是 VS 专用命令行。排掉这两类问题,编译基本能顺利通过。
4.3 装完之后检查三个文件
不管走哪条路线,装完都建议手动确认一下目标目录里有没有对应文件。我习惯用 PowerShell 检查:
ls "C:\Program Files\PostgreSQL\17\lib\vector.dll" ls "C:\Program Files\PostgreSQL\17\share\extension\vector.control" ls "C:\Program Files\PostgreSQL\17\share\extension\vector--*.sql"这三个文件缺一不可。缺了 DLL,数据库加载阶段就会报错;缺了 control 文件,连识别这个扩展都识别不了;缺了 SQL 脚本,CREATE EXTENSION会提示找不到安装脚本。把这一步当成安装是否成功的硬性验收标准,能省掉后面排查的很多时间。
5. 建扩展与验证:把问题集中在 5 分钟内暴露出来
文件都放好之后,现在终于到了激动人心的时刻。重新连接 PostgreSQL,执行:
CREATE EXTENSION vector;正常情况下会返回CREATE EXTENSION。这一步如果出问题,大概率集中在三种类型。
第一种:could not open extension control file "C:/Program Files/PostgreSQL/17/share/extension/vector.control": No such file or directory。这个错误很清楚,control 文件没放对位置,或者文件名的版本和你CREATE EXTENSION时请求的版本对不上。去share/extension目录看一眼,确认文件存在且文件名包含正确的版本号。
第二种:could not load library "C:/Program Files/PostgreSQL/17/lib/vector.dll": The specified module could not be found。这个报错很迷惑,因为 DLL 文件明明就在那里。真实原因往往是两种:一是编译的 PostgreSQL 大版本和你当前运行的不一致,SQL 文件版本对上了,但 DLL 是另一个版本编译的,ABI 不兼容;二是系统里缺了 Microsoft Visual C++ Redistributable 运行库,pgvector 依赖 MSVC 运行环境,而这个不是每台 Windows 都预装的。建议去微软官网下载最新的 vc_redist.x64.exe 装上,然后重试。
第三种:extension "vector" has no installation script nor update path。这是 SQL 脚本没放进去,或者说脚本版本号和 control 文件里的版本号不一致。检查share/extension下的文件名,确保vector--x.y.z.sql里的版本号和 control 文件列出的default_version一致。
成功创建扩展之后,用 psql 执行几条 SQL 做快速验证:
SELECT '[1,2,3]'::vector; SELECT vector_dims('[1,2,3]'::vector); SELECT '[1,2,3]'::vector <-> '[4,5,6]'::vector;第一条确认类型能被解析,第二条显示维度应该是 3,第三条计算两个三维向量之间的欧氏距离,结果是 5.196...(也就是 √27)。三条都返回正常,扩展就算真正装好了。如果前面有任何一步失败,回到第 4 章的验收标准重新检查文件,别急着乱调参数。
6. 跑一个最小 Demo:向量写入、距离查询与 HNSW 索引
扩展建好之后,整个安装旅程算完成了 80%。剩下的 20% 是验证它真正能用于实际查询。下面这个 Demo 很短,但把建表、插入、排序、建索引全串起来了。
先建一张带向量字段的表:
CREATE TABLE items ( id bigserial PRIMARY KEY, content text NOT NULL, embedding vector(3) );这里的vector(3)是维度设置。实际项目中,如果用的是 OpenAI 的 embedding 模型,维度通常是 1536;用本地开源模型可能是 384 或 1024。测试阶段用 3 维就够了,方便肉眼观察距离。
插入几条数据:
INSERT INTO items (content, embedding) VALUES ('苹果', '[0.1,0.2,0.3]'), ('香蕉', '[0.4,0.5,0.6]'), ('天气', '[0.7,0.8,0.9]');然后查一下“和[0.2,0.3,0.4]这个向量最相似的前两条记录”:
SELECT id, content, embedding <-> '[0.2,0.3,0.4]' AS distance FROM items ORDER BY distance LIMIT 2;这里的<->是欧氏距离运算符。pgvector 一共提供了三种距离语义,在不同场景下要选对:
<->:欧氏距离,适合直接比较向量在空间中的直线距离<=>:余弦距离,适合文本相似度、语义搜索这类对向量模长不敏感的场景<#>:负内积,适合已经归一化过的向量,能拿到更高的检索效率
数据量小的时候,直接全表扫描就能出结果。但如果你要做的是几百条以上的真实检索,索引是必须的。pgvector 支持两种索引,我建议优先用 HNSW:
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);这条语句创建 HNSW 索引,vector_l2_ops对应的是欧氏距离。如果你存的是文本 embedding、打算用余弦距离查询,那应该建vector_cosine_ops。HNSW 索引的好处是不需要训练、写入即建、查询速度快,适用于大多数中小规模场景。另一种 IVFFlat 索引则需要先有数据、再指定聚类中心数量lists去训练,调起来更麻烦,除非数据量到了百万级以上,否则没必要优先选它。
建立索引后,用EXPLAIN ANALYZE验证查询是否真的走索引:
EXPLAIN ANALYZE SELECT id, content, embedding <-> '[0.2,0.3,0.4]' AS distance FROM items ORDER BY distance LIMIT 2;如果执行计划里出现Index Scan using items_embedding_idx,说明索引生效了。如果还是Seq Scan,大概率是表太小,优化器觉得全表扫更快——这不是故障,数据量上去之后自然会切到索引。
7. Windows 特有的坑位清单:能一次装完的人不多
照理说写到第 6 章,安装流程已经完整了。但这套流程我在 Windows 上反反复复装了很多次,几乎每次都冒出几个稀奇古怪的问题,这里统一列一份避坑清单,你按顺序排查基本能解决 90% 的麻烦。
PATH 环境变量没生效。很多人配置完 PATH 之后没有重新打开终端,直接在当前窗口敲psql,命令当然找不到。配置 PATH 之后必须新开一个命令行窗口,或者干脆注销重登一次。否则你查来查去,浪费的纯粹是自己的时间。
VS 命令行架构不对。编译 pgvector 必须用 x64 的命令行工具。如果打开的是 x86 Native Tools,编译产物就是 32 位的 DLL,放到 64 位的 PostgreSQL 里照样加载失败。怎么确认?命令行窗口标题通常会写 x64 或 x86,如果标题上没写,执行echo %VSCMD_ARG_TGT_ARCH%,输出为 x64 才对。
DLL 加载失败但文件存在。前面提到过可能是缺 VC++ 运行库,这是 Windows 用户最隐蔽的坑。PostgreSQL 官方安装包自带了一部分运行库,但扩展编译依赖的新版运行库不一定在系统里。下载vc_redist.x64.exe装上再重试,大部分情况下都能解决。
版本混用的连锁反应。我见过有人下载了最新版 pgvector,却拿它去配旧版 PostgreSQL,报错之后又换一个版本,最后整个share/extension目录里躺着好几个版本的 vector 文件。PostgreSQL 扩展的机制是版本号严格匹配的,vector.control里写的是哪个版本,SQL 脚本就必须对应哪个版本。保持目录干净,删除不用的旧文件,只留一个版本。
端口被占用导致服务起不来。如果你曾经装过其他数据库或开发组件,5432 有可能被抢先占了。检查方式:netstat -ano | findstr 5432,看看对应的 PID 到底是谁。确认是无关进程占用的,可以在 PostgreSQL 的配置文件postgresql.conf里改端口,或者干脆杀掉占用进程,再重启服务。
中文数据乱码。psql 是命令行程序,在中文 Windows 上默认字符集可能不是 UTF-8。往表里插中文之前先执行SET client_encoding TO 'UTF8';,否则查询结果可能出现乱码,但数据本身不一定坏了。如果数据库已经存在错误编码的数据,建议用 pgAdmin 的 Query Tool 重新插入,图形界面在这方面不那么容易出问题。
卸载残留导致重装异常。Windows 卸载 PostgreSQL 时,不会自动清理C:\Program Files\PostgreSQL\17\share\extension目录下的扩展文件。如果你之前装过 pgvector 后来又卸载了数据库,重装新版本后再执行CREATE EXTENSION,可能会加载到残留的旧文件。解决办法是在新安装之前,把 PostgreSQL 安装目录整个删干净,再开始装。
最后分享一个我的习惯:现在我在 Windows 上装这类扩展,已经固定成一套流程——先上 GitHub Releases 页面看有没有现成二进制,有就直接拷贝,省时省力;没有就开 VS 工具链编译,而不会在普通 cmd 里硬折腾 nmake,浪费一整个下午。这套顺序基本能让我十分钟内搞定 pgvector 的安装,也希望这篇记录能帮你少踩几个 Windows 特有的坑。