常见问题

本文汇总了向量数据库使用过程中的常见问题。

存储

单个表可存储多少向量?

默认情况下,非分区表的最大限制为32 TB,而分区表可以拥有数千个该大小的分区。

是否支持复制?

支持。PGVector使用WAL日志,支持复制和时间点恢复。

如果索引超过2,000维怎么办?

可选择支持更高维度的索引类型:

  • Halfvec:半精度向量,最多支持4,000维。

  • Bit:位向量,最多支持64,000维。

或将索引降维

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

支持。可使用vector类型代替vector(3)

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_highpre (id bigserial PRIMARY KEY, embedding double precision[]);

-- 对于Postgres数组,使用 {} 而不是 []
INSERT INTO items_highpre (embedding) VALUES ('{1,2,3}'), ('{4,5,6}');

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

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

通过表达式索引创建HNSW索引:

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

创建索引成功后,使用以下方式查询:

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

是否需要将索引完全放入内存?

不需要。但是和其他索引类型一样,放入内存可获得更好的性能表现。您可通过以下语句查看索引大小:

SELECT pg_size_pretty(pg_relation_size('index_name'));

查询处理

为什么查询没有使用索引?

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

-- 使用索引
ORDER BY embedding <=> '[3,1,2]' LIMIT 5;

-- 不使用索引
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索引后查询结果减少?

索引可能是在列表数量较多而使用的数据较少的情况下创建的。请在表中数据量增加后再重新创建索引,或考虑先删除现有索引。

此外,其查询结果可能受到探针数量ivfflat.probes限制。可启用迭代索引扫描帮助解决此问题。

需要注意的是,NULL向量不会被索引,对于余弦距离,零向量也同样不会被索引。