向量数据库
向量数据库是 RAG 应用的核心基础设施,负责存储和检索高维向量。与传统数据库不同,它不按精确匹配查询,而是按相似度查找最近邻向量。这种能力让 AI 能够理解语义层面的关联,而非字面匹配。
向量存储原理
向量是文本的数值化表示,通过 Embedding 模型将文本映射到高维空间(如 1536 维)。语义相近的文本在这个空间中距离更近,通过余弦相似度、欧氏距离等度量计算相关性。向量数据库的核心是高效存储这些向量,并在毫秒级完成大规模相似度搜索。
传统数据库的 B-Tree 索引不适合向量检索,因为高维空间的距离计算需要遍历所有数据。暴力搜索的时间复杂度是 O(n),n 是向量数量,当 n 达到百万级时延迟不可接受。近似最近邻(ANN)算法通过牺牲少量精度换取数百倍的性能提升,是向量数据库的核心技术。
HNSW 算法
HNSW (Hierarchical Navigable Small World) 是目前最流行的 ANN 算法。它借鉴了跳表的思想,构建多层图结构:顶层是稀疏图,节点少但能快速定位区域;底层是稠密图,覆盖所有节点用于精确搜索。搜索时从顶层开始,逐层向下逼近目标,类似"先坐飞机到城市,再打车到街道"的分层导航。
HNSW 的构建过程是贪心的:每个新节点在每层随机选择一定数量的邻居,优先连接距离最近的节点。查询时从顶层随机节点出发,每层找到距离目标最近的邻居,进入下一层,直到底层返回结果。这种结构的查询复杂度是 O(log n),构建复杂度是 O(n log n),参数 ef_controls 构建和查询的精度-效率权衡。
HNSW 的优势在于查询速度快、召回率高,缺点是内存占用大(需要存储图结构)和构建成本高(大规模数据插入慢)。对于静态或低频更新的数据集,HNSW 是最佳选择;对于高频插入场景,可以考虑 IVF(倒排文件)或 DiskANN(磁盘优化)。
主流方案选型
Milvus 是开源向量数据库的代表,支持多种索引类型(HNSW、IVF、DiskANN)、多种部署模式(单机、分布式、云服务)。它的架构设计将存储和计算分离,数据持久化到对象存储(MinIO、S3),计算节点弹性扩展。Milvus 适合大规模生产环境,但运维复杂度较高,需要部署多个组件(etcd、Pulsar、MinIO)。
Chroma 是轻量级选择,纯 Python 实现,嵌入到应用进程,无需独立部署。它默认用 DuckDB 存储向量,支持持久化到磁盘。Chroma 的优势是零配置、易集成,适合原型开发和小规模应用(百万级向量以下)。缺点是性能和扩展性有限,不支持分布式。
Pinecone 是托管服务,无需运维,按查询次数计费。它提供自动扩缩容、数据备份、安全认证等生产特性,适合不想维护基础设施的团队。Pinecone 的 API 设计简洁,但从国内访问速度慢,数据存储在海外,需要考虑合规问题。
Weaviate 是另一个开源方案,支持向量搜索和全文过滤的混合查询。它的特色是内置模块化:可以集成 OpenAI、Cohere 的 Embedding 模型,支持 GraphQL 查询语言。Weaviate 适合需要多模态搜索(文本、图像、音频)的场景。
PostgreSQL + pgvector 是折中选择。pgvector 扩展给 PostgreSQL 添加了向量类型和相似度操作符,可以用熟悉的 SQL 查询。优势是不需要引入新的数据库,向量数据和业务数据在同一系统,事务一致性更好。缺点是性能不如专用向量数据库,适合中小规模(千万级以下)和已有 PostgreSQL 的场景。
相似度计算
余弦相似度是文本检索的标准度量,计算两个向量夹角的余弦值,范围 [-1, 1],值越大越相似。它只关注方向,忽略长度,适合归一化的 Embedding 向量。欧氏距离计算向量空间的直线距离,范围 [0, +∞],值越小越相似。内积是余弦相似度的未归一化版本,计算速度更快,但需要向量长度归一化。
选择度量需要结合 Embedding 模型和业务场景。OpenAI 的 text-embedding-3 模型推荐用余弦相似度,因为输出向量已归一化。如果需要绝对距离判断(如阈值过滤),欧氏距离更直观。内积适合极致性能场景,但要确保向量预处理正确。
数据管理
向量导入是批量任务的高频场景。百万级向量应该用批量插入而非循环单条,Milvus 支持 insert API 一次性插入数万条。导入前需要预处理:文本清洗(去除 HTML、特殊字符)、向量化(调用 Embedding 模型)、维度对齐(检查与数据库配置一致)。导入时可以禁用索引构建,导入完成后再重建,避免增量更新的性能损耗。
数据更新和删除需要考虑索引重建。HNSW 索引的删除只是标记数据无效,实际空间不释放,需要定期 compaction。更新操作等同于删除+插入,会改变向量的位置,可能影响查询精度。对于频繁变化的数据,选择 IVFFlat 或 IVFPQ 索引更合适,它们的更新成本更低。
数据分区是大规模部署的必要手段。Milvus 支持按字段值分区,比如按用户 ID 分区,查询时只搜索相关分区,减少扫描范围。时间序列数据可以按时间分区,旧数据用廉价存储,热数据用高性能索引。分区的键应该选择高基数字段(区分度高)和查询频繁字段。
性能优化
索引参数调优直接影响性能和精度。HNSW 的 M 参数控制每层最大连接数,默认 16,增大提升召回率但增加内存和构建时间。ef_construction 控制构建时的候选队列大小,默认 200,增大提升索引质量但构建变慢。ef_search 控制查询时的候选队列大小,增大提升召回率但查询变慢。调优时可以在测试集上用不同参数组合,找到精度-延迟的最优点。
量化技术降低内存占用。PQ (Product Quantization) 将向量分解成多个子向量,每个子向量用聚类中心替代,存储空间从 4byte/float 降到 1byte/cluster。SQ (Scalar Quantization) 将每个浮点数转换为 8bit 整数,空间降到 1/4。量化的代价是精度损失,需要在测试集上评估。对于 GPU 部署,量化还能提升计算吞吐量(8bit 比 3232 快得多)。
缓存策略减少重复查询。Redis 可以缓存热门查询的结果,key 是查询向量的哈希,value 是 top-k 结果。缓存命中率取决于数据的重复度,客服机器人、FAQ 查询等场景缓存效果明显。缓存更新需要考虑数据新鲜度,可以设置 TTL 或者数据变更时主动失效。
监控指标是性能基线的保证。需要关注查询延迟(P50、P99)、QPS、召回率(用标注数据集验证)、内存使用率、CPU/GPU 利用率。告警规则应该捕获延迟突增(可能是索引失效)、内存溢出(批量导入过大)、QPS 下降(节点故障)。Prometheus + Grafana 是标准方案,Milvus、Pinecone 都内置了 metrics 端点。
混合查询
纯向量搜索有时不够精确,需要结合元数据过滤。比如"查找关于机器学习的文档,且发布日期在 2024 年之后",向量搜索找到语义相关的文档,元数据过滤缩小范围。实现方式有两种:先过滤后搜索(在过滤后的集合上做 ANN),或者先搜索后过滤(在 ANN 结果上应用条件)。前者精度高但过滤条件必须支持索引,后者简单但可能返回少于 k 个结果。
多路召回融合不同来源的结果。向量搜索返回语义相关的文档,关键词搜索返回字面匹配的文档,两者可以合并、去重、重排序。融合策略包括加权分数、倒数排名融合(RRF)、学习排序(用模型预测最相关结果)。多路召回在电商搜索、文档搜索等场景效果显著,不同召回方式互补,减少漏召。