pgvector向量数据库使用
传统数据库依赖结构化数据的精确匹配,但无法高效处理文本、图像、音频等非结构化数据的语义相似性需求 —— 这类数据需通过Word2Vec、BERT、CNN等向量生成算法转换为高维特征向量,向量的距离直接对应数据的 相似度。随着 AI大模型、RAG的爆发,海量向量的高效存储、快速相似性检索(Top-K 查询)需求激增。传统数据库缺乏专门的向量索引和计算优化,全表扫描效率极低,因此向量数据库应运而生 —
一、概述
传统数据库依赖结构化数据的精确匹配,但无法高效处理文本、图像、音频等非结构化数据的语义相似性需求 —— 这类数据需通过Word2Vec、BERT、CNN等向量生成算法转换为高维特征向量,向量的距离直接对应数据的 相似度。
随着 AI大模型、RAG的爆发,海量向量的高效存储、快速相似性检索(Top-K 查询)需求激增。传统数据库缺乏专门的向量索引和计算优化,全表扫描效率极低,因此向量数据库应运而生 —— 它专为高维向量设计,通过优化存储结构、向量索引算法和并行计算,解决海量向量的快速相似匹配 核心痛点。
二、pgvector简介
pgvector是一个为 PostgreSQL 数据库设计的 开源扩展插件 (Extension)。它的核心功能是为 PostgreSQL 增加了对 高维向量 (Vector) 的原生支持。核心特点:
- 无缝集成PostgreSQL:可以在表中创建vector类型的列,像操作普通数据类型一样操作向量,支持标准的 SELECT, INSERT, UPDATE, DELETE 语句,以及与其他数据类型的混合查询。
- 支持多种距离度量:包括欧几里得距离 (<->)、余弦距离(<=>)、曼哈顿距离(<+>)等。
- 高性能向量索引:pgvector 提供了两种强大的近似最近邻索引HNSW和IVFFlat。HNSW查询速度极快,召回率高,但内存占用较大,构建索引较慢,适合对查询性能要求极致的场景;IVFFlat构建速度快,内存占用较小。通过调整
probe参数可以在召回率和查询速度之间做权衡。适合对内存敏感或数据更新频繁的场景。
三、pgvector使用
1、安装pgvector
前提是已经安装好PostgreSQL,然后找到与PostgreSQL对应版本的pgvector并进行安装。
apt install postgresql-16-pgvector
2、启用pgvector
连接到目标数据库后执行如下命令:
CREATE EXTENSION vector;
可通过以下方式确认pgvector是否安装成功:
\dx vector
3、使用pgvector
创建向量表并插入数据:
CREATE TABLE items (
id bigserial PRIMARY KEY,
name varchar(100),
features vector(3)
);
INSERT INTO items (name, features) VALUES ('高性能游戏本', '[10, 8, 9]');
INSERT INTO items (name, features) VALUES ('轻薄办公本', '[6, 9, 7]');
INSERT INTO items (name, features) VALUES ('长续航平板电脑', '[5, 7, 10]');
INSERT INTO items (name, features) VALUES ('入门级笔记本', '[4, 6, 5]');
INSERT INTO items (name, features) VALUES ('专业图形工作站', '[9, 5, 8]');
4、pgvector查询运算符
pgvector 主要提供了三个二元运算符,用于计算两个向量之间的距离。
|
运算符 |
距离类型 |
含义 |
适用场景 |
|
<-> |
欧几里得距离 (Euclidean Distance) |
计算两个向量在 n 维空间中的 “直线距离”。距离越小,向量越相似。 |
当向量的绝对数值有意义时,例如:推荐系统中的用户行为统计、图像像素比较。 |
|
<=> |
余弦距离 (Cosine Distance) |
计算两个向量方向的差异(基于夹角)。结果范围在 0 到 2 之间。距离越小,向量方向越一致。 |
当只关心向量的 ** 方向(语义)** 是否相似时,例如:语义搜索、文本相似度比较、词嵌入(Word Embeddings)。这是最常用的场景。 |
|
<+> |
曼哈顿距离 (Manhattan Distance) |
计算两个向量在各个维度上距离差的绝对值之和(“街区距离”)。距离越小,向量越相似。 |
当数据维度代表独立的、可累加的路径或成本时,例如:路径规划、特征差异总和。 |
示例 1:使用余弦距离 (<=>) 查找最相似的物品
这是在语义搜索中最常用的场景。假设我们有一个查询向量 [8, 7, 8],我们想找到特征最接近它的物品。
SELECT
id,
name,
features,
-- 计算并显示与查询向量的余弦距离
features <=> '[8, 7, 8]' AS cosine_distance
FROM
items
ORDER BY
-- 按余弦距离升序排序,最相似的排在前面
features <=> '[8, 7, 8]'
LIMIT 3;
查询结果如下:
id | name | features | cosine_distance
----+----------------+----------+----------------------
1 | 高性能游戏本 | [10,8,9] | 0.001165212470104371
5 | 专业图形工作站 | [9,5,8] | 0.01420861940174456
4 | 入门级笔记本 | [4,6,5] | 0.023498633049285234
(3 rows)
结果显示,“高性能游戏本” 与查询向量 [8, 7, 8] 的余弦距离最小,因此是最相似的。
示例 2:使用欧几里得距离 (<->) 查找最近的物品
如果我们关心的是数值上的绝对差异,我们可以使用欧几里得距离。
SELECT
id,
name,
features,
features <-> '[8, 7, 8]' AS euclidean_distance
FROM
items
ORDER BY
features <-> '[8, 7, 8]'
LIMIT 3;
查询结果如下:
id | name | features | euclidean_distance
----+----------------+----------+--------------------
5 | 专业图形工作站 | [9,5,8] | 2.23606797749979
1 | 高性能游戏本 | [10,8,9] | 2.449489742783178
2 | 轻薄办公本 | [6,9,7] | 3
(3 rows)
5、pgvector索引
当你的数据表非常大时,上述查询会变得非常缓慢,因为它需要对表中的每一行都进行一次向量计算(全表扫描)。为了解决这个问题,pgvector 支持创建向量索引,它能极大地加速相似度查询。
1)创建 HNSW 索引 (推荐用于高维度、追求召回率):HNSW (Hierarchical Navigable Small Worlds) 是一种高效的近似最近邻(ANN)算法,非常适合高维度向量。
-- 为 features 列创建 HNSW 索引,使用余弦距离
CREATE INDEX items_features_idx ON items USING hnsw (features vector_cosine_ops);
-- 为 features 列创建 HNSW 索引,使用欧几里得距离
-- CREATE INDEX items_features_idx ON items USING hnsw (features vector_l2_ops);
注:创建索引时需要指定操作符类 (vector_cosine_ops或vector_l2_ops),它必须与你查询时使用的运算符相匹配。
- <=> (余弦距离) 对应 vector_cosine_ops
- <-> (欧几里得距离) 对应 vector_l2_ops
- <+> (曼哈顿距离) 对应 vector_l1_ops
2)创建 IVFFlat 索引 (推荐用于低维度、追求速度):IVFFlat (Inverted File with Flat Compression) 将向量空间划分为多个单元(lists),查询时只在少数几个单元中进行搜索。
-- 创建 IVFFlat 索引,使用余弦距离,并指定 100 个单元 (lists)
-- lists 的数量通常设置为数据集大小的平方根左右
CREATE INDEX items_features_idx ON items USING ivfflat (features vector_cosine_ops) WITH (lists = 100);
3)使用索引进行查询
创建索引后,不需要修改之前的 SELECT 查询语句。PostgreSQL 的查询优化器会自动选择使用索引来加速查询。
-- 这个查询现在会使用 items_features_idx 索引,速度会快得多
SELECT id, name
FROM items
ORDER BY features <=> '[8, 7, 8]'
LIMIT 5;
你可以使用 EXPLAIN ANALYZE 来验证索引是否被使用:
EXPLAIN ANALYZE
SELECT id, name FROM items ORDER BY features <=> '[8, 7, 8]' LIMIT 5;
在执行计划中,你应该能看到 Index Scan using items_features_idx。
更多推荐
所有评论(0)