news 2026/10/7 15:06:18

内存不够怎么办:VexDB-Lite PQ 量化索引教程,把向量存储压缩到几分之一

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
内存不够怎么办:VexDB-Lite PQ 量化索引教程,把向量存储压缩到几分之一

内存不够怎么办:VexDB-Lite PQ 量化索引教程,把向量存储压缩到几分之一

【免费下载链接】VexDB-LiteA cross-platform vector database, which can be integrated into existing databases as a plugin.项目地址: https://gitcode.com/gh_mirrors/ve/VexDB-Lite

VexDB-Lite 是一个可插入 PostgreSQL、DuckDB、SQLite 的跨平台向量数据库插件,内置PQ(Product Quantization,乘积量化)量化索引:建索引时把每个向量用训练好的码本编码成几十字节的短码,索引侧存储直接缩小到原始向量的几分之一,特别适合内存紧张但又要跑向量相似度检索的场景。本文面向新手,讲清楚 PQ 是什么、能省多少内存,以及三种数据库里怎么写出一条 PQ 索引。

一、为什么向量检索总"吃内存"

一条 768 维的 embedding(常见于文本/图像向量)按 float32 存储就是 768 × 4 =3072 字节。100 万条向量的裸向量文件约3 GB——这还没算图索引的拓扑结构和查询时的缓存。机器只有 8 GB 内存时,索引直接加载进来基本就"OOM 预演"了。

VexDB-Lite 的图索引默认会把向量留在索引侧参与距离计算;开启 PQ 后,索引侧只保留量化码,原始向量留在业务表里,查询时再按需取回精确重排。官方压测报告中,100 万条 768 维向量的物理存储从 3.4 GB 级别压缩到 1.2 GB 级别(见 Cohere-1M 复测报告),量级思路与 PQ 一致:索引越瘦,内存越宽裕。

二、PQ 量化原理:把 768 维"切成小段"记编码

PQ 的思路非常直观,三步走:

  1. 切段:把向量切成pq_m段(子向量)。例如 128 维向量、pq_m = 32,每段 4 维。
  2. 训练码本:对每段用 K-means 聚成 256 个簇心(代码见 common/quantizer/product_quantizer.h 与 common/quantizer/annkmeans.h),形成码本。
  3. 编码:每个向量的每段只记录"落在哪个簇心",1 个字节即可表示。

于是压缩比一目了然:

向量维度原始大小(float32)PQ 码大小(pq_m=32)压缩比
128512 B32 B约 1/16
7683072 B32 B约 1/96
1536(多模态 embedding)6144 B64 B(pq_m=64)约 1/96

怎么选pq_m?唯一硬性要求是pq_m必须能整除向量维度。经验值是每段 4~8 维效果最好(源码里也有同样的AutoSelectM逻辑,见 product_quantizer.h),即pq_m ≈ dim / 4,768 维用 32~192 都合理,128 维用 16~32。段数越多,压缩越狠,但召回损失也越大——这是本文后面"调召回"一节要解决的。

三、PostgreSQL:一条 WITH 子句开启 PQ 索引

完整语法示例在 README.md 里,核心就两步:

SET maintenance_work_mem = '2GB'; -- 训练需要内存,内存不足会回退成普通图索引 CREATE INDEX idx_pq ON items USING vexdb_graph (vec floatvector_l2_ops) WITH (quantizer = 'pq', pq_m = 4);

几个新手最容易踩的点:

  • 训练样本要够:训练样本少于 256 条、或内存预算太低时,PQ 会回退成普通图索引并给出 NOTICE,不会报错——建完记得检查。
  • 训练在主进程跑:parallel_workers > 0时,并行 worker 只参与磁盘构建阶段,码本训练仍在 leader 进程完成,所以maintenance_work_mem给主进程留足。
  • 建完仍可增删改:PQ 索引支持建后INSERT/UPDATE/DELETE,新向量直接用已训练好的码本编码,不用重建。
  • compact 模式是强约束:memory_mode='compact'下量化器必须激活,样本或内存不足时直接报错而不是静默回退,适合生产上"我就要压缩"的严格场景。

四、DuckDB 与 SQLite:compact 模式极限压缩

DuckDB(语法见 documentation/features.md):

CREATE INDEX idx_pq ON items USING GRAPH_INDEX (vec) WITH (quantizer = 'pq', pq_m = 32); -- 紧凑模式:索引侧不再保留原始向量镜像 CREATE INDEX idx_compact ON items USING GRAPH_INDEX (vec) WITH (quantizer = 'pq', pq_m = 32, memory_mode = 'compact');

SQLite直接在建虚拟表时指定(完整示例见 vexdb_sqlite/README.md):

CREATE VIRTUAL TABLE idx USING GRAPH_INDEX( embedding FLOAT[128], metric=cosine, quantizer=pq, pq_m=32, memory_mode=compact );

SQLite 侧的细节:PQ 按ef_search × 1.25扩展候选,再用%_vectors里的原向量做精确重排,所以 compact 下业务数据仍然完整,只是索引 blob 不再写原始向量镜像。

五、PQ 之后怎么调召回和速度

PQ 码算出的距离是"近似距离",VexDB-Lite 用精确重排找回召回:先按 PQ 距离筛出一批候选,再取原始向量精算距离排序。三个关键旋钮(DuckDB 侧):

参数默认作用
vexdb_ef_search64图搜索宽度,调大提升召回
vexdb_pq_refine_k_factor1.0重排倍率,1.0 = 不额外扩展;设 4.0 会按 top k×4 用 PQ 筛候选再精排
vexdb_pq_search_mode'off'设'pq_only'跳过精确重排,速度最快但召回略低

实用策略:先默认跑一遍看 recall,不够再调大ef_search;仍不够且延迟可接受,把pq_refine_k_factor提到 2.0~4.0。对应行为有完整测试用例覆盖,可参考 graph_index_pq.yaml 与 graph_index_pq_refine.yaml。

六、建完索引怎么确认"真的量化了"

三个动作养成习惯:

  1. 查状态:PG 用SELECT indexname, use_pq, pq_m FROM vexdb_index_info();,DuckDB 用SELECT * FROM vexdb_index_info();。
  2. 看内存模式:PG 的 compact 模式下,ALTER INDEX ... SET不会重写已有索引,必须REINDEX后用vexdb_index_info()与index_inspect()(关注Working Quantizer、Vector Storage两个属性)确认实际状态。
  3. 跑一遍 ANN 查询:ORDER BY vec <-> '...' LIMIT 10,优化器会自动改写成索引扫描,确认走的是量化路径而不是全表扫。

小结:内存不够时的决策清单

  • 向量维度高(≥768)+ 内存紧张 → 直接 PQ + compact,收益最大(约 1/96 压缩);
  • pq_m取dim/4左右且整除维度,兼顾压缩比与召回;
  • PG 记得给maintenance_work_mem留训练空间,小表(<256 样本)别开 PQ;
  • 建完用vexdb_index_info()验证,再用ef_search/ refine 倍率两档调召回。

更多参数与三种引擎的差异对照,推荐通读 功能文档;想从源码理解量化内核(K-means 训练、ADC 距离表、SIMD 分发),入口在 common/quantizer/ 目录。

【免费下载链接】VexDB-LiteA cross-platform vector database, which can be integrated into existing databases as a plugin.项目地址: https://gitcode.com/gh_mirrors/ve/VexDB-Lite

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 15:06:16

pstack原则09类型系统纪律:如何让非法状态不可表示

pstack原则09类型系统纪律&#xff1a;如何让非法状态不可表示 【免费下载链接】pstack-claude Claude Code, Codex, Copilot, Pi, OpenCode, Gemini, and Prime Agent versions of Potetos pstack. Rigorous agent workflows with Cursor primitives translated for other har…

作者头像 李华
网站建设 2026/10/7 15:06:15

HarmonyOS 7 ImageAnimator:长动图帧时序修正与前后台恢复

一、那张“偶尔加速”的动图没有坏 FramePulseLab 原本只是一个动效素材验收页&#xff1a;设计同学把 metro_signals.gif 放进 resources/rawfile&#xff0c;开发侧显示帧数、原始时长和当前生命周期&#xff0c;确认无误后再把素材交给业务页面。文件是 720720、48 帧&#…

作者头像 李华
网站建设 2026/10/7 15:05:35

UR3与Realsense L515手眼标定实战:从AX=XB到抓取精度校准

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 15:05:22

Linux 内存回收机制:水位线、kswapd 与 Direct Reclaim

Linux 内存回收机制&#xff1a;水位线、kswapd 与 Direct Reclaim源码基线&#xff1a;Linux v6.18.9&#xff08;mm/page_alloc.c / mm/vmscan.c&#xff09;。 现象&#xff1a;内存明明还有&#xff08;free 数 GB&#xff09;&#xff0c;进程却偶发卡顿几百毫秒&#xff…

作者头像 李华
网站建设 2026/10/7 15:05:08

AI 练习项目 智能数仓问答

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/7 15:05:01

云数据中心特点

云数据中心特点&#xff1a;资源池化。通过虚拟化技术将计算&#xff0c;存储和网络资源统一整合&#xff0c;形成共享资源池&#xff0c;提高资源利用率。按需服务&#xff0c;根据业务需求动态分配和回收资源&#xff0c;实现资源的弹性供给。高可靠性&#xff0c;采用冗余设…

作者头像 李华