现场是这样的。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 以内再重新生成向量更省事。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
