深入 pgvector:在 PostgreSQL 中构建高效的向量相似性搜索

作为一名开发者,你是否曾面临过这样一个挑战:既要利用传统关系型数据库(如 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 实现了 IVFFlatHNSW 两种高效的近似最近邻索引,能在毫秒级返回结果。

环境准备与安装实战

为了让你能够完全理解这一过程,我们将从最基础的环境搭建开始。让我们在 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‘;"

!Screenshot-2025-10-28-103923

第 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 现在已经具备了处理向量的超能力。

!Screenshot-2025-10-28

数据操作与向量查询

现在让我们进入实际操作环节。我们将创建一个表,写入一些模拟数据,并执行一次向量相似性搜索。

第 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‘ 的距离会非常大。这就是向量搜索的本质:寻找多维空间中的“最近邻”。

!Screenshot-2025-10-28-103910

深入理解:运算符与索引

在上面的例子中,我们使用了 运算符。这是 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(检索增强生成)应用中了。探索吧,数据之间的关系远比你想象的更紧密!

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/32390.html
点赞
0.00 平均评分 (0% 分数) - 0