pgvector 调优是什么
pgvector 的检索性能由三部分共同决定:索引类型与参数、构建期资源、查询期资源。构建 HNSW 或 IVFFlat 索引时受 maintenance_work_mem 影响,内存不足会让构建退化成慢速路径;查询期用 hnsw.ef_search 或 ivfflat.probes 在召回与延迟之间取舍;未走索引的顺序扫描则可以借 max_parallel_workers_per_gather 并行提速。调优的第一步不是照抄参数,而是用 EXPLAIN ANALYZE 确认执行计划到底走了什么。
基本信息
| 适用环境 | PostgreSQL 加 pgvector 扩展 |
|---|---|
| 索引类型 | HNSW(推荐)与 IVFFlat |
| 构建期参数 | maintenance_work_mem(会话级可调) |
| 查询期参数 | hnsw.ef_search、ivfflat.probes |
| 并行参数 | max_parallel_workers_per_gather |
| 诊断手段 | EXPLAIN (ANALYZE, BUFFERS) |
典型使用场景
- 大表建索引前临时调大维护内存,避免构建时间失控
- 排查慢查询:确认是否走了向量索引,还是退化为顺序扫描
- 召回不足时提高 ef_search 或 probes,再评估延迟代价
- 批量灌库:先灌数据后建索引,避免边写边维护索引
- 高并发下限制并行度,避免一条查询吃满 CPU 影响其他业务
构建期与查询期参数
构建期与查询期参数
-- 建索引前(仅当前会话生效)
SET maintenance_work_mem = '2GB';
CREATE INDEX ON kb_chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64); -- m 是每层连接数,ef_construction 是构建候选宽度
-- 查询期
SET max_parallel_workers_per_gather = 4; -- 允许并行
SET hnsw.ef_search = 100; -- 查询候选集放大,召回上升延迟也上升
EXPLAIN (ANALYZE, BUFFERS)
SELECT id FROM kb_chunks ORDER BY embedding <=> $1 LIMIT 10; -- 看执行计划关键参数读法
| 参数 | 作用 | 调整方向 |
|---|---|---|
| maintenance_work_mem | 建索引可用内存 | 大表建索引前会话级调大,但不要超过机器内存上限 |
| hnsw.ef_search | HNSW 查询候选集大小 | 调大召回上升、延迟上升 |
| ivfflat.probes | IVFFlat 扫描的列表数 | 调大召回上升、延迟上升 |
| max_parallel_workers_per_gather | 单查询并行工作进程数 | 大表顺序扫描提速,但会占用更多 CPU |
| EXPLAIN 输出 | 执行计划 | 出现 Index Scan 才算真正用上向量索引 |
用 EXPLAIN ANALYZE 确认是否走索引扫描:大表上的顺序扫描通常比索引慢一个量级,先定位再调参。
SET 只对当前会话生效,写进 postgresql.conf 的改动需要重载或重启;线上临时调优优先用会话级 SET,可控且易回退。
HNSW 的 m 与 ef_construction 只在建索引那一刻生效,改完必须重建索引才对已有数据起作用;日常可调的只有查询期的 hnsw.ef_search。
IVFFlat 用 lists 决定聚类列表数,pgvector 文档的建议是百万行以内取行数除以一千的量级、更大规模取行数的平方根量级;查询期再用 ivfflat.probes 控制扫描多少列表。