现场是这样的。pgvector 0.8 上把 text-embedding-3-large 的 3072 维原样存进 vector(3072) 列,建索引时报 ERROR: column cannot have more than 2000 dimensions for hnsw index,换成 ivfflat 也一样。

中间走过弯路,把「直接降到 1536 维后没重新归一化,相似度偏移」当成主因,改完现象没变。

真正麻烦的地方在于,几个原因的现象几乎一样。vector 类型的 HNSW 与 IVFFlat 都有 2000 维硬上限;halfvec 支持到 4000 维,但没换类型;索引建在表达式上,维度校验走了另一条路径。

先确认扩展版本与列类型

psql "$PG_URL" -c "select extversion from pg_extension where extname='vector'; select attname, format_type(atttypid, atttypmod) from pg_attribute where attrelid='chunks'::regclass and attname='embedding';"

随后把列改成 halfvec 并保留 3072 维

psql "$PG_URL" -c "alter table chunks alter column embedding type halfvec(3072) using embedding::halfvec(3072);"

再往下在 halfvec 列上重建 HNSW 索引

psql "$PG_URL" -c "create index concurrently on chunks using hnsw (embedding halfvec_cosine_ops) with (m=16, ef_construction=64);"

等前面都确认过,再查询时把参数转成同一类型再比对

psql "$PG_URL" -c "select id from chunks order by embedding <=> '[0.1,0.2]'::halfvec(3072) limit 5;"

同样的操作我在测试机上先走了一遍,线上只做验证过的部分。

怎么算真的好了,看的是同一批现象。建索引成功,执行计划里出现 Index Scan using chunks_embedding_idx,同样的查询延迟从 2.4 秒降到 80 毫秒。

维度上限是类型限制不是配置项,硬降维会损失召回,优先换 halfvec;如果模型支持 dimensions 参数,降到 2000 以内再重新生成向量更省事。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。

作者 9823189