当前位置:   article > 正文

PGVector 管理工具 pgAdmin_pg-vector管理工具

pg-vector管理工具

pgAdmin 下载地址

https://www.postgresql.org/ftp/pgadmin/pgadmin4/

pgAdmin 安装

双击 pgadmin4-*-x64.exe 安装文件,选择安装路径,后面安装提示单击 next 就可以了。

pgAdmin 使用

打开 pgAdmin,单击 “Add New Server”,
在这里插入图片描述
输入 Name,
在这里插入图片描述
输入 Connection 信息,

在这里插入图片描述
单击 Save,就可以连接这个数据库

在这里插入图片描述

pgvector 命令

入门

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

CREATE EXTENSION vector;
  • 1

创建 3 维向量列,

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

插入向量,

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

通过L2距离获取最近邻居,

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

还支持内积 ( <#> ) 和余弦距离 ( <=> )
注意: <#> 返回负内积,因为 Postgres 仅支持运算符上的 ASC 顺序索引扫描

存储

创建一个带有向量列的新表,

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

或者向现有表添加向量列,

ALTER TABLE items ADD COLUMN embedding vector(3);
  • 1

插入向量,

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

更新插入向量,

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

更新向量,

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

删除向量,

DELETE FROM items WHERE id = 1;
  • 1

查询

获取向量的最近邻,

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

获取一行中最近的邻居,

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

获取一定距离内的行,

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

注意:与 ORDER BY 和 LIMIT 结合使用索引

获取距离,

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

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

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

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

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

平均向量,

SELECT AVG(embedding) FROM items;
  • 1

平均向量组,

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

索引

默认情况下,pgvector 执行精确的最近邻搜索,从而提供完美的检索率(perfect recall)。

您可以添加索引以使用近似最近邻搜索,这会牺牲一些检索率来换取速度。与典型索引不同,添加近似索引后,您将看到不同的查询结果。

支持的索引类型有:

  • IVFFlat
  • HNSW (0.5.0 版本中添加)

IVFFlat

IVFFlat 索引将向量划分为列表,然后搜索这些列表中最接近查询向量的子集。与 HNSW 相比,它的构建时间更快,使用的内存更少,但查询性能较低(在速度与调用权衡方面)。

实现良好检索率(good recall)的三个关键是:

  1. 当表有一些数据后创建索引
  2. 选择适当数量的列表 - 对于最多 1M 行,最好从 rows / 1000 开始;对于超过 1M 行,最好从 sqrt(rows) 开始
  3. 查询时,指定适当的探针数量(检索率越高,速度越低) - 一个好的起点是 sqrt(lists)

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

L2距离,

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

内积(Inner product)

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

余弦距离,

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

最多可以索引 2,000 个维度的向量。

指定探针数量(默认为1),

SET ivfflat.probes = 10;
  • 1

较高的值以速度为代价提供更好的检索率,并且可以将其设置为精确最近邻搜索的列表数量(此时规划器将不会使用索引)

在事务内使用 SET LOCAL 将其设置为单个查询,

BEGIN;
SET LOCAL ivfflat.probes = 10;
SELECT ...
COMMIT;
  • 1
  • 2
  • 3
  • 4

使用 Postgres 12+ 检查索引进度,

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

IVFFlat 的阶段是:

  1. initializing
  2. performing k-means
  3. assigning tuples
  4. loading tuples

注意: % 仅在 loading tuples 阶段填充

HNSW

HNSW 索引创建多层图。与 IVFFlat 相比,它的构建时间更慢并且使用更多的内存,但具有更好的查询性能(在速度与调用权衡方面)。没有像 IVFFlat 那样的训练步骤,因此可以在表中没有任何数据的情况下创建索引。

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

L2距离,

CREATE INDEX ON items USING hnsw (embedding vector_l2_ops);
  • 1

内积(Inner product),

CREATE INDEX ON items USING hnsw (embedding vector_ip_ops);
  • 1

余弦距离,

CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops);
  • 1

最多可以索引 2,000 个维度的向量。

指定 HNSW 参数,

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

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

SET hnsw.ef_search = 100;
  • 1

较高的值提供更好的检索率,但代价是速度。

在事务内使用 SET LOCAL 将其设置为单个查询,

BEGIN;
SET LOCAL hnsw.ef_search = 100;
SELECT ...
COMMIT;
  • 1
  • 2
  • 3
  • 4

使用 Postgres 12+ 检查索引进度,

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

HNSW 的阶段是:

  1. initializing
  2. loading tuples

有几种方法可以使用 WHERE 子句对最近邻居查询进行索引,

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

在一个或多个 WHERE 列上创建索引以进行精确搜索,

CREATE INDEX ON items (category_id);
  • 1

或者向量列上的部分索引以进行近似搜索,

CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops) WITH (lists = 100)
    WHERE (category_id = 123);
  • 1
  • 2

使用分区对 WHERE 列的许多不同值进行近似搜索,

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

与 Postgres 全文搜索一起使用以进行混合搜索。

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

您可以使用倒数排名融合(Reciprocal Rank Fusion)或交叉编码器(cross-encoder)来组合结果。

使用 EXPLAIN ANALYZE 调试性能。

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

要加快没有索引的查询速度,请增加 max_parallel_workers_per_gather

SET max_parallel_workers_per_gather = 4;
  • 1

如果向量标准化为长度 1(如 OpenAI 嵌入),请使用内积以获得最佳性能。

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

要加快使用 IVFFlat 索引的查询速度,请增加倒排列表的数量(以检索率为代价)。

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

FAQ

Q: 一个表中可以存储多少个向量?
A: 默认情况下,Postgres 中非分区表的限制为 32 TB。分区表可以有数千个相同大小的分区。

Q: 支持复制吗?
A: 是的,pgvector 使用预写日志(WAL),它允许复制和时间点恢复。

Q: 如果我想要索引超过 2,000 个维度的向量怎么办?
A: 您现在需要使用降维dimensionality reduction

Q: 我可以将不同维度的向量存储在同一列中吗?
A: 您可以使用 vector 作为类型(而不是 vector(3) )。

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

但是,您只能在具有相同维数的行上创建索引(使用表达式和部分索引):

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

查询:

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

Q: 我可以更精确地存储向量吗?
A: 您可以使用 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}');
  • 1
  • 2
  • 3
  • 4

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

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

使用表达式索引来索引(以较低的精度):

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

查询,

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

向量运算符

OperatorDescriptionAdded
+逐元素加法
-逐元素减法
*逐元素乘法0.5.0
<->欧氏距离
<#>负内积
<=>余弦距离

向量函数

FunctionDescriptionAdded
cosine_distance(vector, vector) → double precision余弦距离
inner_product(vector, vector) → double precision内积
l2_distance(vector, vector) → double precision欧氏距离
l1_distance(vector, vector) → double precisiontaxicab 距离0.5.0
vector_dims(vector) → integer维数
vector_norm(vector) → double precision欧几里得范数

聚合函数

FunctionDescriptionAdded
avg(vector) → vector平均的
sum(vector) → vector0.5.0

完结!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/325433
推荐阅读
相关标签
  

闽ICP备14008679号