Open-source vector similarity search for Postgres
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 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
如果遇到问题,请参阅安装说明
您也可以通过Docker、Homebrew、PGXN、APT、Yum、pkg、APK或conda-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
如果遇到问题,请参阅安装说明。
您也可以通过Docker或conda-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 BY 和 LIMIT 来使用索引
距离
获取距离
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 的阶段包括:
initializing(初始化)loading tuples(加载元组)
IVFFlat
IVFFlat 索引将向量划分为多个列表,然后搜索那些与查询向量最接近的列表子集。它的构建时间更快,内存占用也比 HNSW 少,但查询性能较低(就速度-召回率权衡而言)。
实现良好召回率的三个关键是:
- 在表中已有一些数据之后再创建索引
- 选择适当的列表数量——对于最多 100 万行数据,一个不错的起点是
rows / 1000;对于超过 100 万行数据,则是sqrt(rows) - 查询时,指定适当数量的 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 的阶段如下:
initializing(初始化)performing k-means(执行 k-means 算法)assigning tuples(分配元组)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_tuples 或 ivfflat.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);
为获得最佳性能,请在加载初始数据之后再添加任何索引。
索引
对于大规模场景,可使用 二进制量化 来创建更小的索引并加快构建速度。
在生产环境中,应并发创建索引,以避免阻塞写入操作。
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;
扩展
对于较小的工作集:
- 在表中使用
halfvec类型替代vector类型 - 对索引使用二进制量化(搜索时结合重排序)
通过增加单个实例的内存、CPU 和存储来进行垂直扩展。使用现有工具来调整参数和监控性能。
使用副本进行水平扩展,或者使用 Citus、PgDog 或其他分片方法(示例)。
监控
使用 pg_stat_statements 或 PgHero 等现有工具监控性能。
通过比较近似搜索与精确搜索的结果来监控召回率。
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-ruby、Neighbor |
| 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 indexing或binary quantization可获得更小的索引。
故障排除
为什么查询不使用索引?
查询需要包含ORDER BY和LIMIT,且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 类型),且所有元素必须是有限的(不能是 NaN、Infinity 或 -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 字节的存储空间。每个元素是半精度浮点数,且所有元素必须是有限的(不能是 NaN、Infinity 或 -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 字节的存储空间。每个元素是一个单精度浮点数,且所有元素必须为有限值(不允许 NaN、Infinity 或 -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-trixie、0.8.4-pg18-trixiepg18-bookworm、0.8.4-pg18-bookworm、pg18、0.8.4-pg18pg17-trixie、0.8.4-pg17-trixiepg17-bookworm、0.8.4-pg17-bookworm、pg17、0.8.4-pg17pg16-trixie、0.8.4-pg16-trixiepg16-bookworm、0.8.4-pg16-bookworm、pg16、0.8.4-pg16pg15-trixie、0.8.4-pg15-trixiepg15-bookworm、0.8.4-pg15-bookworm、pg15、0.8.4-pg15pg14-trixie、0.8.4-pg14-trixiepg14-bookworm、0.8.4-pg14-bookworm、pg14、0.8.4-pg14pg13-trixie、0.8.4-pg13-trixiepg13-bookworm、0.8.4-pg13-bookworm、pg13、0.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@18 和 postgresql@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';
致谢
感谢以下项目与文献:
- PASE: PostgreSQL Ultra-High-Dimensional Approximate Nearest Neighbor Search Extension
- Faiss: A Library for Efficient Similarity Search and Clustering of Dense Vectors
- Using the Triangle Inequality to Accelerate k-means
- k-means++: The Advantage of Careful Seeding
- Concept Decompositions for Large Sparse Text Data using Clustering
- Efficient and Robust Approximate Nearest Neighbor Search using Hierarchical Navigable Small World Graphs
历史版本
查看更新日志
贡献指南
我们鼓励所有人为改进此项目贡献力量。您可以通过以下几种方式提供帮助:
开发入门方法:
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
贡献者资源