pgvector:Open-source vector similarity search for Postgres

Open-source vector similarity search for Postgres

分支133Tags40
文件最后提交记录最后更新时间
16 天前
1 天前
1 天前
21 小时前
3 年前
3 年前
1 天前
1 天前
5 个月前
1 天前
1 天前
1 天前
1 天前
1 天前

pgvector

Postgres 的开源向量相似度搜索工具

将向量与其他数据一同存储。支持以下功能:

  • 精确和近似最近邻搜索
  • 单精度、半精度、二进制和稀疏向量
  • L2 距离、内积、余弦距离、L1 距离、汉明距离和杰卡德距离
  • 任何拥有 Postgres 客户端的语言

此外,还具备 ACID 合规性、时间点恢复、JOIN 操作以及 Postgres 的所有其他出色功能

向量数量庞大?可使用量化进行扩展

构建状态

安装

Linux 和 Mac

编译并安装扩展(支持 Postgres 13+)

cd /tmp
git clone --branch v0.8.4 https://github.com/pgvector/pgvector.git
cd pgvector
make
make install # may need sudo

如果遇到问题,请参阅安装说明

您也可以通过DockerHomebrewPGXNAPTYumpkgAPKconda-forge进行安装,它已预安装在Postgres.app和许多托管提供商中。此外,还有适用于GitHub Actions的说明。

Windows

确保已安装Visual Studio 中的 C++ 支持,并以管理员身份运行“x64 Native Tools Command Prompt for VS [version]”。然后使用nmake进行构建:

set "PGROOT=C:\Program Files\PostgreSQL\18"
cd %TEMP%
git clone --branch v0.8.4 https://github.com/pgvector/pgvector.git
cd pgvector
nmake /F Makefile.win
nmake /F Makefile.win install

如果遇到问题,请参阅安装说明

您也可以通过Dockerconda-forge进行安装。

快速开始

启用扩展(在每个要使用该扩展的数据库中执行一次)

CREATE EXTENSION vector;

创建一个具有 3 个维度的向量列

CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));

插入向量

INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');

通过 L2 距离获取最近邻

SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;

同时支持内积(<#>)、余弦距离(<=>)和 L1 距离(<+>

注意:<#> 返回的是负内积,因为 Postgres 仅支持对运算符进行 ASC 顺序的索引扫描

存储

创建一个包含向量列的新表

CREATE TABLE items (id bigserial PRIMARY KEY, embedding vector(3));

或者向现有表中添加一个 vector 列

ALTER TABLE items ADD COLUMN embedding vector(3);

同时支持半精度二进制稀疏向量

插入向量

INSERT INTO items (embedding) VALUES ('[1,2,3]'), ('[4,5,6]');

也可以使用 COPY 批量加载向量(示例

COPY items (embedding) FROM STDIN WITH (FORMAT BINARY);

Upsert 向量

INSERT INTO items (id, embedding) VALUES (1, '[1,2,3]'), (2, '[4,5,6]')
    ON CONFLICT (id) DO UPDATE SET embedding = EXCLUDED.embedding;

更新向量

UPDATE items SET embedding = '[1,2,3]' WHERE id = 1;

删除向量

DELETE FROM items WHERE id = 1;

查询

获取与向量最邻近的向量

SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;

支持的距离函数包括:

  • <-> - L2 距离
  • <#> - (负)内积
  • <=> - 余弦距离
  • <+> - L1 距离
  • <~> - 汉明距离(二进制向量)
  • <%> - 杰卡德距离(二进制向量)

获取与某一行最邻近的邻居

SELECT * FROM items WHERE id != 1 ORDER BY embedding <-> (SELECT embedding FROM items WHERE id = 1) LIMIT 5;

获取特定距离范围内的行

SELECT * FROM items WHERE embedding <-> '[3,1,2]' < 5;

注意:结合 ORDER BYLIMIT 来使用索引

距离

获取距离

SELECT embedding <-> '[3,1,2]' AS distance FROM items;

对于内积,需乘以 -1(因为 <#> 返回的是负内积)

SELECT (embedding <#> '[3,1,2]') * -1 AS inner_product FROM items;

对于余弦相似度,请使用 1 - 余弦距离

SELECT 1 - (embedding <=> '[3,1,2]') AS cosine_similarity FROM items;

聚合函数

向量平均值

SELECT AVG(embedding) FROM items;

向量组的平均值

SELECT category_id, AVG(embedding) FROM items GROUP BY category_id;

索引

默认情况下,pgvector 执行精确最近邻搜索,可提供完美的召回率。

您可以添加索引以使用近似最近邻搜索,这种方式会以牺牲部分召回率为代价来换取速度提升。与常规索引不同,添加近似索引后,查询结果可能会有所不同。

支持的索引类型包括:

HNSW

HNSW 索引会构建一个多层图结构。在速度-召回率权衡方面,其查询性能优于 IVFFlat,但构建时间更长,内存占用也更大。此外,由于不像 IVFFlat 那样需要训练步骤,即使表中没有数据也可以创建索引。

请为您希望使用的每个距离函数添加一个索引。

L2 距离

CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);

注意:对于 halfvec 类型,请使用 halfvec_l2_ops;对于 sparsevec 类型,请使用 sparsevec_l2_ops(其他距离函数的使用方式类似)

内积

CREATE INDEX ON items USING hnsw (embedding vector_ip_ops);

余弦距离

CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);

L1 距离

CREATE INDEX ON items USING hnsw (embedding vector_l1_ops);

汉明距离

CREATE INDEX ON items USING hnsw (embedding bit_hamming_ops);

杰卡德距离

CREATE INDEX ON items USING hnsw (embedding bit_jaccard_ops);

支持的类型包括:

  • vector - 最多 2,000 维
  • halfvec - 最多 4,000 维
  • bit - 最多 64,000 维
  • sparsevec - 最多 1,000 个非零元素

索引选项

指定 HNSW 参数

  • m - 每层的最大连接数(默认值为 16)
  • ef_construction - 构建图时动态候选列表的大小(默认值为 64)
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops) WITH (m = 16, ef_construction = 64);

ef_construction 的值越高,召回率越好,但会增加索引构建时间和插入速度。

查询选项

指定搜索的动态候选列表大小(默认值为 40)

SET hnsw.ef_search = 100;

值越高,召回率越好,但速度会相应降低。

在事务中使用 SET LOCAL 可为单个查询设置该参数。

BEGIN;
SET LOCAL hnsw.ef_search = 100;
SELECT ...
COMMIT;

索引构建时间

当图能够放入 maintenance_work_mem 时,索引的构建速度会显著提升。

SET maintenance_work_mem = '8GB';

当图不再适用时,会显示一条通知

NOTICE:  hnsw graph no longer fits into maintenance_work_mem after 100000 tuples
DETAIL:  Building will take significantly more time.
HINT:  Increase maintenance_work_mem to speed up builds.

注意:不要将 maintenance_work_mem 设置得过高,以免耗尽服务器内存

与其他索引类型类似,在加载初始数据后创建索引会更快

你还可以通过增加并行工作进程的数量(默认值为 2)来加快索引创建速度

SET max_parallel_maintenance_workers = 7; -- plus leader

对于大量工作进程,你可能需要增加 max_parallel_workers(默认值为 8)

索引选项 对构建时间也有显著影响(除非召回率较低,否则使用默认值)

大规模场景下,使用 二进制量化 可加快构建速度

索引构建进度

查看 索引构建进度

SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;

HNSW 的阶段包括:

  1. initializing(初始化)
  2. loading tuples(加载元组)

IVFFlat

IVFFlat 索引将向量划分为多个列表,然后搜索那些与查询向量最接近的列表子集。它的构建时间更快,内存占用也比 HNSW 少,但查询性能较低(就速度-召回率权衡而言)。

实现良好召回率的三个关键是:

  1. 在表中已有一些数据之后再创建索引
  2. 选择适当的列表数量——对于最多 100 万行数据,一个不错的起点是 rows / 1000;对于超过 100 万行数据,则是 sqrt(rows)
  3. 查询时,指定适当数量的 probes(探针)(探针数量越多,召回率通常越好;数量越少,速度通常越快)——一个不错的起点是 sqrt(lists)

为每个要使用的距离函数添加一个索引。

L2 距离

CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100);

注意:对于 halfvec 类型,请使用 halfvec_l2_ops(其他距离函数的使用方式类似)

内积

CREATE INDEX ON items USING ivfflat (embedding vector_ip_ops) WITH (lists = 100);

余弦距离

CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

汉明距离

CREATE INDEX ON items USING ivfflat (embedding bit_hamming_ops) WITH (lists = 100);

支持的类型包括:

  • vector - 最多 2,000 维
  • halfvec - 最多 4,000 维
  • bit - 最多 64,000 维

查询选项

指定探测数(默认值为 1)

SET ivfflat.probes = 10;

值越高,召回率越好,但速度会下降。若要进行精确最近邻搜索,可将其设置为列表数量(此时规划器将不会使用索引)

在事务内使用 SET LOCAL 可为单个查询设置该值

BEGIN;
SET LOCAL ivfflat.probes = 10;
SELECT ...
COMMIT;

索引构建时间

通过增加并行工作进程数量(默认值为 2),可以加快大型表的索引创建速度。

SET max_parallel_maintenance_workers = 7; -- plus leader

对于大量工作进程,你可能还需要增加 max_parallel_workers(默认值为 8)

索引进度

查看索引进度

SELECT phase, round(100.0 * tuples_done / nullif(tuples_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;

IVFFlat 的阶段如下:

  1. initializing(初始化)
  2. performing k-means(执行 k-means 算法)
  3. assigning tuples(分配元组)
  4. loading tuples(加载元组)

注意:% 仅在 loading tuples(加载元组)阶段填充。

过滤

有几种方法可以为带有 WHERE 子句的最近邻查询建立索引。

SELECT * FROM items WHERE category_id = 123 ORDER BY embedding <-> '[3,1,2]' LIMIT 5;

一个不错的起点是在过滤列上创建索引。在许多情况下,这可以提供快速、精确的最近邻搜索。Postgres 为此提供了多种索引类型:B-tree(默认)、哈希、GiST、SP-GiST、GIN 和 BRIN。

CREATE INDEX ON items (category_id);

对于多列,请考虑使用multicolumn index

CREATE INDEX ON items (location_id, category_id);

精确索引适用于匹配低百分比行的条件。否则,近似索引可能效果更好。

CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);

使用近似索引时,过滤是在索引扫描之后应用的。如果某个条件匹配 10% 的行,在使用 HNSW 且默认 hnsw.ef_search 为 40 的情况下,平均只会匹配到 4 行。若需匹配更多行,请启用迭代索引扫描,它会在需要时自动扫描更多索引内容。

SET hnsw.iterative_scan = strict_order;

如果仅按少数几个不同的值进行筛选,可考虑使用 partial indexing

CREATE INDEX ON items USING hnsw (embedding vector_l2_ops) WHERE (category_id = 123);

如果需要按多种不同的值进行筛选,请考虑使用分区

CREATE TABLE items (embedding vector(3), category_id int) PARTITION BY LIST(category_id);

迭代索引扫描

对于近似索引,带过滤条件的查询可能返回较少结果,因为过滤是在索引扫描之后应用的。从 0.8.0 版本开始,您可以启用迭代索引扫描,它会自动扫描更多索引内容,直到找到足够的结果(或者达到 hnsw.max_scan_tuplesivfflat.max_probes 的限制)。

迭代扫描可以使用严格排序或宽松排序。

严格排序确保结果按距离精确排序。

SET hnsw.iterative_scan = strict_order;

Relaxed 允许结果在距离排序上略有偏差,但能提供更好的召回率

SET hnsw.iterative_scan = relaxed_order;
# or
SET ivfflat.iterative_scan = relaxed_order;

通过宽松排序,您可以使用物化 CTE 来获得严格排序

WITH relaxed_results AS MATERIALIZED (
    SELECT id, embedding <-> '[1,2,3]' AS distance FROM items WHERE category_id = 123 ORDER BY distance LIMIT 5
) SELECT * FROM relaxed_results ORDER BY distance + 0;

注意:Postgres 17+ 版本需要使用 + 0

对于按距离进行筛选的查询,为获得最佳性能,请使用物化 CTE 并将距离筛选条件放在 CTE 外部(这是由于 Postgres 执行器的当前行为

WITH nearest_results AS MATERIALIZED (
    SELECT id, embedding <-> '[1,2,3]' AS distance FROM items ORDER BY distance LIMIT 5
) SELECT * FROM nearest_results WHERE distance < 5 ORDER BY distance;

注意:将所有其他筛选条件放在 CTE 内

迭代扫描选项

由于扫描近似索引的大部分内容成本较高,因此有一些选项可控制扫描何时结束。

HNSW

指定要访问的最大元组数量(默认值为 20,000)

SET hnsw.max_scan_tuples = 20000;

注意:这只是近似值,不会影响初始扫描

指定要使用的最大内存量,以 work_mem 的倍数表示(默认值为 1)

SET hnsw.scan_mem_multiplier = 2;

注意:如果增加 hnsw.max_scan_tuples 未能提高召回率,请尝试增大此值。

IVFFlat

指定最大探针数量

SET ivfflat.max_probes = 100;

注意:如果此值低于 ivfflat.probes,则会使用 ivfflat.probes

半精度向量

使用 halfvec 类型存储半精度向量

CREATE TABLE items (id bigserial PRIMARY KEY, embedding halfvec(3));

半精度索引

以半精度对向量建立索引,以获得更小的索引体积

CREATE INDEX ON items USING hnsw ((embedding::halfvec(3)) halfvec_l2_ops);

获取最近邻

SELECT * FROM items ORDER BY embedding::halfvec(3) <-> '[1,2,3]' LIMIT 5;

二进制向量

使用 bit 类型存储二进制向量(示例

CREATE TABLE items (id bigserial PRIMARY KEY, embedding bit(3));
INSERT INTO items (embedding) VALUES ('000'), ('111');

通过汉明距离获取最近邻

SELECT * FROM items ORDER BY embedding <~> '101' LIMIT 5;

还支持 Jaccard 距离(<%>

二进制量化

使用表达式索引进行二进制量化

CREATE INDEX ON items USING hnsw ((binary_quantize(embedding)::bit(3)) bit_hamming_ops);

通过汉明距离获取最近邻

SELECT * FROM items ORDER BY binary_quantize(embedding)::bit(3) <~> binary_quantize('[1,-2,3]') LIMIT 5;

通过原始向量重新排序以提高召回率

SELECT * FROM (
    SELECT * FROM items ORDER BY binary_quantize(embedding)::bit(3) <~> binary_quantize('[1,-2,3]') LIMIT 20
) ORDER BY embedding <=> '[1,-2,3]' LIMIT 5;

稀疏向量

使用 sparsevec 类型存储稀疏向量

CREATE TABLE items (id bigserial PRIMARY KEY, embedding sparsevec(5));

插入向量

INSERT INTO items (embedding) VALUES ('{1:1,3:2,5:3}/5'), ('{1:4,3:5,5:6}/5');

格式为{index1:value1,index2:value2}/dimensions,且索引从 1 开始,与 SQL 数组类似

通过 L2 距离获取最近邻

SELECT * FROM items ORDER BY embedding <-> '{1:3,3:1,5:2}/5' LIMIT 5;

混合搜索

与 Postgres 全文搜索 结合使用,实现混合搜索。

SELECT id, content FROM items, plainto_tsquery('hello search') query
    WHERE textsearch @@ query ORDER BY ts_rank_cd(textsearch, query) DESC LIMIT 5;

你可以使用 Reciprocal Rank Fusion交叉编码器 来组合结果。

子向量索引

使用表达式索引对子向量进行索引

CREATE INDEX ON items USING hnsw ((subvector(embedding, 1, 3)::vector(3)) vector_cosine_ops);

通过余弦距离获取最近邻

SELECT * FROM items ORDER BY subvector(embedding, 1, 3)::vector(3) <=> subvector('[1,2,3,4,5]'::vector, 1, 3) LIMIT 5;

通过完整向量重新排序以提高召回率

SELECT * FROM (
    SELECT * FROM items ORDER BY subvector(embedding, 1, 3)::vector(3) <=> subvector('[1,2,3,4,5]'::vector, 1, 3) LIMIT 20
) ORDER BY embedding <=> '[1,2,3,4,5]' LIMIT 5;

性能

调优

使用 PgTune 之类的工具来设置 Postgres 服务器参数的初始值。例如,shared_buffers 通常应设为服务器内存的 25%。你可以通过以下方式找到配置文件:

SHOW config_file;

并使用以下命令检查各项设置:

SHOW shared_buffers;

请务必重启 Postgres 以使更改生效。

存储

对于较小的工作集,使用 halfvec 类型而非 vector

加载

使用 COPY 进行批量数据加载(示例)。

COPY items (embedding) FROM STDIN WITH (FORMAT BINARY);

为获得最佳性能,请在加载初始数据之后再添加任何索引。

索引

请参阅 HNSWIVFFlat 的索引构建时间。

对于大规模场景,可使用 二进制量化 来创建更小的索引并加快构建速度。

在生产环境中,应并发创建索引,以避免阻塞写入操作。

CREATE INDEX CONCURRENTLY ...

查询

使用 EXPLAIN (ANALYZE, BUFFERS) 调试性能。

EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM items ORDER BY embedding <-> '[3,1,2]' LIMIT 5;

精确搜索

若要在不使用索引的情况下加快查询速度,请增大 max_parallel_workers_per_gather

SET max_parallel_workers_per_gather = 4;

如果向量已归一化为长度 1(例如 OpenAI embeddings),请使用内积以获得最佳性能。

SELECT * FROM items ORDER BY embedding <#> '[3,1,2]' LIMIT 5;

近似搜索

结合二进制量化与重排序,可在大规模场景下将索引保持在内存中。

若要使用 IVFFlat 索引加快查询速度,可增加倒排列表的数量(但会以牺牲召回率为代价)。

CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 1000);

清理

HNSW 索引的清理过程可能需要一段时间。可以先通过重建索引来加快清理速度。

REINDEX INDEX CONCURRENTLY index_name;
VACUUM table_name;

扩展

对于较小的工作集:

  1. 在表中使用 halfvec 类型替代 vector 类型
  2. 对索引使用二进制量化(搜索时结合重排序)

通过增加单个实例的内存、CPU 和存储来进行垂直扩展。使用现有工具来调整参数监控性能

使用副本进行水平扩展,或者使用 CitusPgDog 或其他分片方法(示例)。

监控

使用 pg_stat_statementsPgHero 等现有工具监控性能。

通过比较近似搜索与精确搜索的结果来监控召回率。

BEGIN;
SET LOCAL enable_indexscan = off; -- use exact search
SELECT ...
COMMIT;

编程语言

通过任意带有 Postgres 客户端的语言即可使用 pgvector。您甚至可以在一种语言中生成并存储向量,然后在另一种语言中对其进行查询。

语言 库 / 示例
Ada pgvector-ada
Algol pgvector-algol
C pgvector-c
C++ pgvector-cpp
C#、F#、Visual Basic pgvector-dotnet
COBOL pgvector-cobol
Crystal pgvector-crystal
D pgvector-d
Dart pgvector-dart
Elixir pgvector-elixir
Erlang pgvector-erlang
Fortran pgvector-fortran
Gleam pgvector-gleam
Go pgvector-go
Haskell pgvector-haskell
Java、Kotlin、Groovy、Scala pgvector-java
JavaScript、TypeScript pgvector-node
Julia Pgvector.jl
Lisp pgvector-lisp
Lua pgvector-lua
Nim pgvector-nim
OCaml pgvector-ocaml
Pascal pgvector-pascal
Perl pgvector-perl
PHP pgvector-php
Prolog pgvector-prolog
Python pgvector-python
R pgvector-r
Racket pgvector-racket
Raku pgvector-raku
Ruby pgvector-rubyNeighbor
Rust pgvector-rust
Swift pgvector-swift
Tcl pgvector-tcl
Zig pgvector-zig

常见问题

单个表中可以存储多少个向量?

Postgres 中默认非分区表的大小限制为 32 TB。分区表可以包含数千个该大小的分区。

是否支持复制?

支持,pgvector 使用预写日志(WAL),支持复制和时间点恢复。

如果想要为超过 2000 维的向量建立索引怎么办?

可以使用半精度向量半精度索引为最多 4000 维的向量建立索引,或使用二进制量化为最多 64000 维的向量建立索引。其他选项包括子向量索引(适用于支持该功能的模型)或降维

能否在同一列中存储不同维度的向量?

可以使用 vector 作为类型(而非 vector(n))。

CREATE TABLE embeddings (model_id bigint, item_id bigint, embedding vector, PRIMARY KEY (model_id, item_id));

不过,你只能对具有相同维度数量的行创建索引(可使用表达式部分索引):

CREATE INDEX ON embeddings USING hnsw ((embedding::vector(3)) vector_l2_ops) WHERE (model_id = 123);

并使用以下方式查询:

SELECT * FROM embeddings WHERE model_id = 123 ORDER BY embedding::vector(3) <-> '[3,1,2]' LIMIT 5;

能否以更高精度存储向量?

您可以使用 double precision[]numeric[] 类型来存储更高精度的向量。

CREATE TABLE items (id bigserial PRIMARY KEY, embedding double precision[]);

-- use {} instead of [] for Postgres arrays
INSERT INTO items (embedding) VALUES ('{1,2,3}'), ('{4,5,6}');

可选择添加检查约束,以确保数据可以转换为vector类型并具有预期的维度。

ALTER TABLE items ADD CHECK (vector_dims(embedding::vector) = 3);

使用 表达式索引 来创建索引(精度较低):

CREATE INDEX ON items USING hnsw ((embedding::vector(3)) vector_l2_ops);

并使用以下方式查询:

SELECT * FROM items ORDER BY embedding::vector(3) <-> '[3,1,2]' LIMIT 5;

索引是否需要放入内存?

不需要,但与其他索引类型一样,如果能放入内存,性能可能会更好。您可以通过以下方式获取索引大小:

SELECT pg_size_pretty(pg_relation_size('index_name'));

使用half-precision indexingbinary quantization可获得更小的索引。

故障排除

为什么查询不使用索引?

查询需要包含ORDER BYLIMIT,且ORDER BY必须是距离运算符(而非表达式)的结果,并按升序排列。

-- index
ORDER BY embedding <=> '[3,1,2]' LIMIT 5;

-- no index
ORDER BY 1 - (embedding <=> '[3,1,2]') DESC LIMIT 5;

你可以通过以下方式鼓励查询优化器在查询中使用索引:

BEGIN;
SET LOCAL enable_seqscan = off;
SELECT ...
COMMIT;

此外,如果表很小,表扫描可能会更快。

为什么查询不使用并行表扫描?

规划器在成本估算中不考虑行外存储,这可能会使串行扫描看起来成本更低。你可以通过以下方式降低查询的并行扫描成本:

BEGIN;
SET LOCAL min_parallel_table_scan_size = 1;
SET LOCAL parallel_setup_cost = 1;
SELECT ...
COMMIT;

或选择将向量内联存储:

ALTER TABLE items ALTER COLUMN embedding SET STORAGE PLAIN;

为什么添加 HNSW 索引后查询结果变少了?

结果受动态候选列表大小(hnsw.ef_search)的限制,默认值为 40。由于查询中的死元组或过滤条件,结果可能会更少。启用迭代索引扫描有助于解决此问题。

此外,请注意 NULL 向量不会被索引(对于余弦距离,零向量也是如此)。

为什么添加 IVFFlat 索引后查询结果变少了?

可能是在创建索引时,数据量相对于列表数量过少。请删除索引,直到表中有更多数据后再重新创建。

DROP INDEX index_name;

结果也可以通过探针数量(ivfflat.probes)来限制。启用迭代索引扫描可以解决此问题。

另外,请注意 NULL 向量不会被索引(余弦距离下的零向量也是如此)。

参考

向量类型

每个向量占用 4 * dimensions + 8 字节的存储空间。每个元素是单精度浮点数(类似于 Postgres 中的 real 类型),且所有元素必须是有限的(不能是 NaNInfinity-Infinity)。向量最多可以有 16,000 个维度。

向量运算符

运算符 描述 新增版本
+ 逐元素加法
- 逐元素减法
* 逐元素乘法 0.5.0
|| 连接 0.7.0
<-> 欧氏距离
<#> 负内积
<=> 余弦距离
<+> 曼哈顿距离 0.7.0

向量函数

函数 描述 新增版本
binary_quantize(vector) → bit 二值量化 0.7.0
cosine_distance(vector, vector) → double precision 余弦距离
inner_product(vector, vector) → double precision 内积
l1_distance(vector, vector) → double precision 曼哈顿距离 0.5.0
l2_distance(vector, vector) → double precision 欧氏距离
l2_normalize(vector) → vector 按欧氏范数归一化 0.7.0
subvector(vector, integer, integer) → vector 子向量 0.7.0
vector_dims(vector) → integer 维度数量
vector_norm(vector) → double precision 欧氏范数

向量聚合函数

函数 描述 新增版本
avg(vector) → vector 平均值
sum(vector) → vector 求和 0.5.0

半精度向量类型

每个半精度向量占用 2 * dimensions + 8 字节的存储空间。每个元素是半精度浮点数,且所有元素必须是有限的(不能是 NaNInfinity-Infinity)。半精度向量最多可以有 16,000 个维度。

Halfvec 运算符

运算符 说明 新增版本
+ 逐元素加法 0.7.0
- 逐元素减法 0.7.0
* 逐元素乘法 0.7.0
|| 拼接 0.7.0
<-> 欧氏距离 0.7.0
<#> 负内积 0.7.0
<=> 余弦距离 0.7.0
<+> 曼哈顿距离 0.7.0

Halfvec 函数

函数 说明 新增版本
binary_quantize(halfvec) → bit 二进制量化 0.7.0
cosine_distance(halfvec, halfvec) → double precision 余弦距离 0.7.0
inner_product(halfvec, halfvec) → double precision 内积 0.7.0
l1_distance(halfvec, halfvec) → double precision 曼哈顿距离 0.7.0
l2_distance(halfvec, halfvec) → double precision 欧氏距离 0.7.0
l2_norm(halfvec) → double precision 欧氏范数 0.7.0
l2_normalize(halfvec) → halfvec 使用欧氏范数进行归一化 0.7.0
subvector(halfvec, integer, integer) → halfvec 子向量 0.7.0
vector_dims(halfvec) → integer 维度数量 0.7.0

Halfvec 聚合函数

函数 说明 新增版本
avg(halfvec) → halfvec 平均值 0.7.0
sum(halfvec) → halfvec 总和 0.7.0

Bit 类型

每个位向量占用 dimensions / 8 + 8 字节的存储空间。更多信息请参见 Postgres 文档

Bit 运算符

运算符 说明 新增版本
<~> 汉明距离 0.7.0
<%> 杰卡德距离 0.7.0

Bit 函数

函数 说明 新增版本
hamming_distance(bit, bit) → double precision 汉明距离 0.7.0
jaccard_distance(bit, bit) → double precision 杰卡德距离 0.7.0

Sparsevec 类型

每个稀疏向量占用 8 * non-zero elements + 16 字节的存储空间。每个元素是一个单精度浮点数,且所有元素必须为有限值(不允许 NaNInfinity-Infinity)。稀疏向量最多可包含 16,000 个非零元素。

稀疏向量运算符

运算符 说明 新增版本
<-> 欧氏距离 0.7.0
<#> 负内积 0.7.0
<=> 余弦距离 0.7.0
<+> 曼哈顿距离 0.7.0

稀疏向量函数

函数 说明 新增版本
cosine_distance(sparsevec, sparsevec) → double precision 余弦距离 0.7.0
inner_product(sparsevec, sparsevec) → double precision 内积 0.7.0
l1_distance(sparsevec, sparsevec) → double precision 曼哈顿距离 0.7.0
l2_distance(sparsevec, sparsevec) → double precision 欧氏距离 0.7.0
l2_norm(sparsevec) → double precision 欧氏范数 0.7.0
l2_normalize(sparsevec) → sparsevec 使用欧氏范数进行归一化 0.7.0

安装说明 - Linux 和 Mac

Postgres 位置

如果您的机器上安装了多个 Postgres,请通过以下方式指定 pg_config 的路径:

export PG_CONFIG=/Library/PostgreSQL/18/bin/pg_config

然后重新运行安装说明(如果需要,在 make 之前运行 make clean)。如果 make install 需要 sudo,请使用:

sudo --preserve-env=PG_CONFIG make install

Mac 上的一些常见路径如下:

  • EDB 安装程序 - /Library/PostgreSQL/18/bin/pg_config
  • Homebrew (arm64) - /opt/homebrew/opt/postgresql@18/bin/pg_config
  • Homebrew (x86-64) - /usr/local/opt/postgresql@18/bin/pg_config

注意:将 18 替换为你的 Postgres 服务器版本

缺少头文件

如果编译失败并显示 fatal error: postgres.h: No such file or directory,请确保服务器上已安装 Postgres 开发文件。

对于 Ubuntu 和 Debian,请使用:

sudo apt install postgresql-server-dev-18

注意:将 18 替换为你的 Postgres 服务器版本

缺少 SDK

如果在 Mac 上编译失败且输出包含 warning: no such sysroot directory,则说明你的 Postgres 安装指向了一个已不存在的路径。

pg_config --cppflags

重新安装 Postgres 以解决此问题。

可移植性

默认情况下,pgvector 在部分平台上会使用 -march=native 进行编译,以获得最佳性能。但如果在其他机器上运行编译后的扩展,可能会导致“非法指令”错误。

如需编译为可移植版本,请使用:

make OPTFLAGS=""

安装说明 - Windows

缺少头文件

如果编译失败并提示 Cannot open include file: 'postgres.h': No such file or directory,请确保 PGROOT 配置正确。

架构不匹配

如果编译失败并提示 error C2196: case value '4' already used,请确保使用的是 x64 Native Tools Command Prompt。然后运行 nmake /F Makefile.win clean 并重新执行安装步骤。

缺少符号

如果在 Postgres 17.0-17.2 版本中链接失败并提示 unresolved external symbol float_to_shortest_decimal_bufn,请升级至 Postgres 17.3 或更高版本。

权限问题

如果安装失败并提示 Access is denied,请以管理员身份重新执行安装步骤。

其他安装方法

Docker

通过以下命令获取 Docker 镜像

docker pull pgvector/pgvector:pg18-trixie

此操作会将 pgvector 添加到 Postgres 镜像 中(请将 18 替换为您的 Postgres 服务器版本,并以相同方式运行)。

支持的标签如下:

  • pg18-trixie0.8.4-pg18-trixie
  • pg18-bookworm0.8.4-pg18-bookwormpg180.8.4-pg18
  • pg17-trixie0.8.4-pg17-trixie
  • pg17-bookworm0.8.4-pg17-bookwormpg170.8.4-pg17
  • pg16-trixie0.8.4-pg16-trixie
  • pg16-bookworm0.8.4-pg16-bookwormpg160.8.4-pg16
  • pg15-trixie0.8.4-pg15-trixie
  • pg15-bookworm0.8.4-pg15-bookwormpg150.8.4-pg15
  • pg14-trixie0.8.4-pg14-trixie
  • pg14-bookworm0.8.4-pg14-bookwormpg140.8.4-pg14
  • pg13-trixie0.8.4-pg13-trixie
  • pg13-bookworm0.8.4-pg13-bookwormpg130.8.4-pg13

您也可以手动构建镜像:

git clone --branch v0.8.4 https://github.com/pgvector/pgvector.git
cd pgvector
docker build --pull --build-arg PG_MAJOR=18 -t myuser/pgvector .

如果增加 maintenance_work_mem,请确保 --shm-size 至少达到该大小,以避免在并行 HNSW 索引构建时出现错误。

docker run --shm-size=1g ...

Homebrew

使用 Homebrew Postgres 时,你可以使用:

brew install pgvector

注意:这仅会将其添加到 postgresql@18postgresql@17 公式中

PGXN

通过 PostgreSQL Extension Network 安装,命令如下:

pgxn install vector

APT

Debian 和 Ubuntu 软件包可从 PostgreSQL APT 仓库 获取。请遵循 设置说明 并运行:

sudo apt install postgresql-18-pgvector

注意:将 18 替换为您的 Postgres 服务器版本

Yum

RPM 包可从 PostgreSQL Yum 仓库 获取。按照针对您的发行版的 设置说明 操作并运行:

sudo yum install pgvector_18
# or
sudo dnf install pgvector_18

注意:将 18 替换为你的 Postgres 服务器版本

软件包

使用以下命令安装 FreeBSD 软件包:

pkg install postgresql17-pgvector

或使用以下端口:

cd /usr/ports/databases/pgvector
make install

APK

使用以下命令安装 Alpine 软件包:

apk add postgresql-pgvector

conda-forge

使用 Conda Postgres 时,可通过 conda-forge 安装,命令如下:

conda install -c conda-forge pgvector

此方法由 @mmcauliffe 通过 社区维护

Postgres.app

下载包含 Postgres 15+ 的 最新版本

托管 Postgres

pgvector 在 这些提供商 处可用。

升级

安装 最新版本(使用与初始安装相同的方法)。然后在每个要升级的数据库中,运行:

ALTER EXTENSION vector UPDATE;

你可以通过以下方式查看当前数据库中的版本:

SELECT extversion FROM pg_extension WHERE extname = 'vector';

致谢

感谢以下项目与文献:

历史版本

查看更新日志

贡献指南

我们鼓励所有人为改进此项目贡献力量。您可以通过以下几种方式提供帮助:

开发入门方法:

git clone https://github.com/pgvector/pgvector.git
cd pgvector
make
make install

要运行所有测试:

make installcheck        # regression tests
make prove_installcheck  # TAP tests

要运行单个测试:

make installcheck REGRESS=functions                            # regression test
make prove_installcheck PROVE_TESTS=test/t/001_ivfflat_wal.pl  # TAP test

要启用断言:

make clean && PG_CFLAGS="-DUSE_ASSERT_CHECKING" make && make install

要启用基准测试:

make clean && PG_CFLAGS="-DHNSW_BENCH -DIVFFLAT_BENCH" make && make install

显示内存使用情况:

make clean && PG_CFLAGS="-DHNSW_MEMORY -DIVFFLAT_MEMORY" make && make install

要获取 k-means 指标:

make clean && PG_CFLAGS="-DIVFFLAT_KMEANS_DEBUG" make && make install

贡献者资源

项目介绍

开源向量相似度搜索工具,适用于Postgres数据库【此简介由AI生成】

定制我的领域
13522.04 K1.23 K访问 GitHub