作为一名开发者,你是否曾面临过这样一个挑战:既要利用传统关系型数据库(如 PostgreSQL)的强大事务处理能力,又需要实现复杂的 AI 驱动功能,比如语义搜索或推荐系统?过去,我们往往需要在 PostgreSQL 之外搭建专门的向量数据库(如 Milvus 或 Pinecone),这不仅增加了架构的复杂性,还带来了数据同步的噩梦。今天,我们将深入探讨一个改变游戏规则的工具——pgvector。这是一个开源的 PostgreSQL 扩展,它能让你直接在数据库内部存储、索引并高效查询高维向量,真正做到“鱼与熊掌兼得”。在这篇文章中,你将学会如何从零开始安装、配置并使用 pgvector,构建一个属于自己的向量搜索系统。
为什么选择 pgvector?
在 AI 和大语言模型(LLM)爆发的时代,数据不再仅仅是文本或数字,更多的是“嵌入”——即将文本、图像或音频转换为高维空间中的数学表示。传统的 SQL LIKE 查询无法理解“苹果”和“水果”之间的语义关系,但向量搜索可以。pgvector 的出现,意味着我们不需要为了向量搜索而迁移数据,也不需要维护两套系统。它让我们能够用熟悉的 SQL 语法,结合 AI 模型,在数百万条记录中瞬间找到最相似的内容。
!<a href="https://media.geeksforgeeks.org/wp-content/uploads/20251212160734526145/vectorrepresentation.webp">vectorrepresentation
pgvector 核心特性一览
在我们动手之前,先来看看它究竟提供了什么核心能力:
- 原生集成: 它不是一个外部服务,而是一个标准的 INLINECODE475156e6 扩展文件。这意味着它完全运行在 PostgreSQL 进程内,享有 ACID 事务保证,配合 INLINECODEc010eaeb 使用极其顺手。
- 灵活的相似性度量: 不同的场景需要不同的数学模型。pgvector 为我们提供了三种核心算法:余弦相似度(Cosine Similarity,侧重方向)、内积(Inner Product,侧重长度和方向)和 L2 距离(Euclidean Distance,欧几里得距离)。
- ANN 索引支持: 如果你要在百万级甚至亿级数据上进行搜索,暴力扫描是不可行的。pgvector 实现了 IVFFlat 和 HNSW 两种高效的近似最近邻索引,能在毫秒级返回结果。
环境准备与安装实战
为了让你能够完全理解这一过程,我们将从最基础的环境搭建开始。让我们在 Linux 环境下(本指南以 Ubuntu/Debian 为例)一步步构建这个系统。
第 1 步:安装基础依赖包
编译 pgvector 需要 PostgreSQL 的开发头文件。我们需要确保系统中不仅安装了数据库本身,还安装了构建工具。
让我们执行以下命令来更新源并安装必要的组件(包括编译器、git 和开发库):
# 更新软件包列表并安装 PostgreSQL 及其开发文件
!apt-get update -qq
!apt-get install -y postgresql postgresql-contrib postgresql-server-dev-14 git make gcc libpq-dev
代码原理解析: 这里 INLINECODE24579fb8 是关键。它包含 INLINECODE74a72932 等头文件,这是 C 语言扩展与 PostgreSQL 内核进行交互的桥梁。
第 2 步:初始化数据库服务
安装完成后,我们需要启动数据库服务,并为默认的超级用户 postgres 设置一个密码,以便后续管理。
# 启动 PostgreSQL 服务
!service postgresql start
# 设置 postgres 用户的密码为 ‘password‘
!sudo -u postgres psql -c "ALTER USER postgres PASSWORD ‘password‘;"
第 3 步:从源码编译 pgvector
这是最激动人心的部分。我们将从 GitHub 官方仓库克隆源码,并将其编译安装到 PostgreSQL 的扩展目录中。
# 克隆 pgvector 源码仓库
!git clone https://github.com/pgvector/pgvector.git
# 进入源码目录
%cd pgvector
# 编译扩展(make 会调用 GCC 编译 C 代码)
!make
# 将编译好的文件安装到 PostgreSQL 的 lib 目录
!make install
# 返回工作目录
%cd /content
技术细节: 当你运行 INLINECODEf27c6eff 时,系统实际上是在将编译好的 INLINECODE90305e44(共享对象库)复制到 PostgreSQL 的 INLINECODEc6022f1c 目录,并将 SQL 控制文件(INLINECODEe6b871de)复制到 extension 目录。这就像是在给 PostgreSQL 安装一个新的“插件”。
第 4 步:启用扩展
编译安装并不代表自动生效。我们需要显式地告诉数据库去加载这个扩展。
# 确保服务正在运行
!service postgresql start
# 在数据库中创建 vector 扩展
!sudo -u postgres psql -c "CREATE EXTENSION IF NOT EXISTS vector;"
如果看到没有报错输出,恭喜你!你的 PostgreSQL 现在已经具备了处理向量的超能力。
数据操作与向量查询
现在让我们进入实际操作环节。我们将创建一个表,写入一些模拟数据,并执行一次向量相似性搜索。
第 5 步:创建表并执行相似性查询
在这里,我们将做几件事:定义表结构、插入数据、并计算查询向量与存储向量之间的距离。
!sudo -u postgres psql -c "
-- 创建一个包含文本和 3 维向量列的表
CREATE TABLE IF NOT EXISTS documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(3)
);
-- 插入三条示例数据
-- 注意:向量使用方括号 [] 表示,类似于数组
INSERT INTO documents (content, embedding) VALUES
(‘AI in healthcare‘, ‘[0.11, 0.45, 0.33]‘),
(‘Machine learning‘, ‘[0.12, 0.44, 0.34]‘),
(‘Cooking recipes‘, ‘[0.87, 0.13, 0.55]‘);
-- 执行查询:
-- 1. 计算每一行 embedding 与查询向量 ‘[0.10,0.46,0.32]‘ 的欧几里得距离(L2距离)
-- 2. 使用 运算符(距离运算符)
-- 3. 按距离升序排序,取前 3 条
SELECT id, content, embedding ‘[0.10,0.46,0.32]‘ AS distance
FROM documents
ORDER BY distance
LIMIT 3;
"
结果解读: 你会发现 ‘AI in healthcare‘ 和 ‘Machine learning‘ 的距离非常小,因为它们在语义空间中靠得很近,而 ‘Cooking recipes‘ 的距离会非常大。这就是向量搜索的本质:寻找多维空间中的“最近邻”。
深入理解:运算符与索引
在上面的例子中,我们使用了 运算符。这是 pgvector 最核心的运算符之一,代表“距离”。但你知道吗?根据应用场景的不同,我们还可以选择不同的运算符和索引。
- 运算符选择:
* :代表 L2 距离(欧几里得距离)。适用于图像特征等需要绝对空间距离的场景。
* :代表 内积(Inner Product)。计算速度极快,适用于已经归一化的向量。
* :代表 余弦相似度。主要关注方向而非大小,非常适合文本语义搜索。
- 关于 IVFFlat 和 HNSW 索引:
如果你只有几千条数据,全表扫描(Sequential Scan)通常很快。但当你拥有百万级数据时,必须建立索引。
* IVFFlat (Inverted File with Flat compression): 这是一个基于聚类的索引。它通过将数据划分为多个“中心点”来加速搜索。使用时,通常建议设置 lists 参数为数据行数的平方根。
* HNSW (Hierarchical Navigable Small World): 这是目前最先进的图索引算法。它的查询速度通常比 IVFFlat 更快,召回率也更高,但构建索引更慢且占用内存更多。
让我们看一个创建 HNSW 索引的例子:
-- 为 documents 表的 embedding 列创建 HNSW 索引,使用余弦距离
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
Python 集成与应用开发
作为开发者,我们很少直接在命令行中使用数据库,更多是通过 Python 等语言进行交互。让我们看看如何在 Python 代码中利用 pgvector。
第 6 步:配置身份验证
PostgreSQL 默认使用 peer 认证(通过操作系统用户),这在脚本化环境中非常不便。我们需要将其修改为密码认证。
# 修改 pg_hba.conf,将本地连接改为 md5 密码验证
!sudo sed -i ‘s/local\s*all\s*postgres\s*peer/local all postgres md5/‘ /etc/postgresql/14/main/pg_hba.conf
# 重启服务使配置生效
!service postgresql restart
# 再次确保密码正确
!sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD ‘password‘;"
第 7 步:使用 Python 连接并进行搜索
最后,我们将使用 Python 的 psycopg2 库连接数据库,并执行一次完整的相似性搜索。
# 安装必要的 Python 床
!pip install psycopg2-binary pgvector
import psycopg2
from pgvector.psycopg2 import register_vector
# 建立数据库连接
conn = psycopg2.connect(
"dbname=postgres user=postgres password=password host=localhost port=5432"
)
# 注册 vector 类型,这样 psycopg2 才能识别并处理 pgvector 的数据
cur = conn.cursor()
register_vector(conn)
# 定义一个查询向量(例如,这是用户输入的一句话经过模型转换后的 Embedding)
query_vector = [0.10, 0.46, 0.32]
# 执行 SQL 查询
# 这里使用 %s 作为占位符,防止 SQL 注入
cur.execute(
"SELECT id, content, embedding %s AS distance FROM documents ORDER BY distance LIMIT 3",
(query_vector,)
)
# 打印结果
results = cur.fetchall()
for row in results:
print(f"ID: {row[0]}, Content: {row[1]}, Distance: {row[2]:.4f}")
cur.close()
conn.close()
实战经验分享: 在实际的生产环境中,你会发现 Python 中的 INLINECODE262ba154 至关重要。如果不调用这个函数,PostgreSQL 返回的向量类型会变成类似 INLINECODEf99c7057 的二进制字节流,导致程序无法解析。此外,当你使用 ORM(如 SQLAlchemy 或 Django)时,虽然 pgvector 通常有专门的适配器,但理解底层的 psycopg2 操作能帮助你更好地排查错误。
总结与最佳实践
通过这篇文章,我们一起完成了从环境搭建到代码实现的全过程。pgvector 极大地降低了将 AI 引入现有数据库系统的门槛。在使用 pgvector 构建应用时,我建议你注意以下几点:
- 性能监控: 始终使用
EXPLAIN ANALYZE来查看你的查询是否真的使用了索引。对于向量查询,忽略索引会导致全表扫描,这在数据量大时是致命的。 - 维度选择: 向量的维度直接影响性能。虽然 pgvector 支持高达 2000 维甚至更高,但在实际应用中,尽量使用模型输出的标准维度(如 OpenAI 的 1536 维),过高或过低都会影响精度。
- 数据归一化: 如果你决定使用余弦相似度,确保在存入数据库之前对向量进行了 L2 归一化处理。这会让搜索结果更加准确,并允许你使用更快的内积运算符。
pgvector 让 PostgreSQL 成为了一个全功能的向量数据库。现在,你可以动手尝试将这一技术集成到你的推荐系统或 RAG(检索增强生成)应用中了。探索吧,数据之间的关系远比你想象的更紧密!