随着RAG(检索增强生成)和AI应用的普及,向量数据库已经从一个小众技术,变成了很多系统的核心组件。

我们团队在过去一年里,把向量数据库从一个实验性的功能,做到了支撑千万级向量、日均百万次查询的生产系统。这个过程中,踩了很多坑,也总结了不少经验。

这篇文章,我想分享一下我们在生产环境使用向量数据库的最佳实践,从选型、索引、数据管理到性能优化,聊聊那些踩过的坑和总结的经验。

为什么需要向量数据库

先简单说说为什么需要向量数据库。

传统的关系型数据库,擅长的是精确匹配和结构化查询。但在AI时代,我们经常需要做的是"相似性搜索":给定一个向量,找到数据库中最相似的N个向量。

比如,在RAG应用中,用户的问题会被转换成一个向量,然后在知识库中找到最相似的文档片段,再把这些片段传给大模型生成答案。这个过程的核心,就是向量的相似性搜索。

向量数据库就是专门为这种场景设计的,它支持高效的向量相似度搜索,支持海量向量的存储和检索,还支持元数据过滤等高级功能。

目前主流的向量数据库有:Milvus、Qdrant、Weaviate、Pinecone、Chroma、pgvector(PostgreSQL的向量扩展)等。各有各的特点,选择的时候要根据自己的需求来。

选型经验

我们在选型的时候,对比了好几个向量数据库,最后选择了Milvus。这里分享一下我们的选型思路。

第一个考虑因素是,规模和性能。我们的场景是千万级向量、日均百万次查询,需要支持水平扩展。Milvus在这方面表现不错,支持分布式部署,性能也很好。如果你的数据量不大(百万级以下),Qdrant或者pgvector可能更轻量、更简单。

第二个考虑因素是,功能完整性。我们需要支持标量过滤、分区、TTL、批量导入等功能。Milvus的功能比较完整,能满足我们的需求。

第三个考虑因素是,运维复杂度。Milvus的运维相对复杂,依赖etcd、MinIO等组件,部署和维护需要一定的经验。如果团队没有专门的运维,Qdrant或者Pinecone(托管服务)可能更省心。

第四个考虑因素是,成本。自建Milvus需要服务器资源,成本相对较高。pgvector可以复用现有的PostgreSQL,成本最低。Pinecone是托管服务,按使用量付费,初期成本低,但量大了之后可能比较贵。

我们的建议是:

  • 数据量小(百万级以下)、团队小:用pgvector或者Qdrant,简单够用。
  • 数据量大(千万级以上)、有运维能力:用Milvus,性能和扩展性好。
  • 不想自己运维、预算充足:用Pinecone或者其他托管服务,省心。

不要盲目追求"最好的"向量数据库,适合自己场景的才是最好的。

索引构建经验

向量数据库的核心是索引,索引的质量直接决定了查询的性能和准确率。

我们在索引构建上踩了不少坑,总结了几个经验。

第一个经验是,选择合适的索引类型。

常见的索引类型有:

  • FLAT:暴力搜索,准确率100%,但速度慢,适合小数据集。
  • IVF_FLAT:倒排文件索引,速度快,准确率略低,适合中等数据集。
  • IVF_SQ8:倒排文件+标量量化,速度更快,内存占用更少,准确率再低一点。
  • HNSW:层次化可导航小世界图,查询速度快,准确率高,内存占用大,适合对延迟要求高的场景。

我们一开始用的是IVF_FLAT,后来发现查询延迟不够稳定,换成了HNSW,延迟降低了很多,准确率也更高。当然,HNSW的内存占用更大,需要根据服务器内存来选择。

第二个经验是,合理设置索引参数。

比如,IVF的nlist参数(聚类中心数量),HNSW的M参数(每层最大连接数)和efConstruction参数(构建时的搜索范围)。这些参数会影响索引的构建速度、内存占用和查询性能。

我们的经验是:

  • nlist一般设置为sqrt(N),其中N是向量数量。比如100万向量,nlist设为1000左右。
  • HNSW的M一般设为16-32,efConstruction设为200-500。
  • 这些参数不是固定的,要根据自己的数据和查询模式来调优。

第三个经验是,索引构建需要时间,不要急。

千万级向量的索引构建,可能需要几个小时甚至更长时间。构建过程中,不要频繁重启服务,也不要同时进行大量写入。我们有一次就是在构建索引的时候大量写入,导致索引构建失败,不得不重来。

第四个经验是,定期重建索引。

随着数据的增删,索引的质量会逐渐下降,查询性能和准确率也会受到影响。我们的做法是,每个月重建一次索引,保持索引的最佳状态。

数据管理经验

向量数据库的数据管理,和传统数据库不太一样,有一些需要特别注意的地方。

第一个注意点是,向量的质量决定了检索的质量。

向量数据库只是存储和搜索向量,向量本身的质量取决于embedding模型。如果embedding模型不好,向量数据库再强也没用。

我们的经验是:

  • 选择适合自己领域的embedding模型。通用模型不一定适合特定领域,有时候需要微调。
  • 文本分块要合理。太大的块会包含太多噪声,太小的块会丢失上下文。我们一般用500-1000字的块,重叠50-100字。
  • 对文本进行预处理。去掉无关的格式、广告、导航等内容,只保留有价值的正文。

第二个注意点是,元数据很重要。

向量数据库不只是存向量,还可以存元数据(比如文档ID、标题、时间、分类等)。元数据可以用来过滤查询结果,提高检索的精准度。

我们的做法是,给每个向量打上丰富的元数据,包括:文档ID、段落序号、分类标签、创建时间、来源等。查询的时候,根据需要用元数据过滤,比如只查某个分类、某个时间段的文档。

第三个注意点是,数据更新要谨慎。

向量数据库的更新操作(删除和重新插入)成本比较高,频繁更新会影响性能。我们的做法是,批量更新,而不是单条更新。每天凌晨低峰期,批量处理当天的增量数据。

第四个注意点是,数据备份不能少。

虽然向量数据库的数据可以从原始文档重新生成,但重新生成embedding和重建索引需要很长时间。我们的做法是,定期备份向量数据库的数据,出了问题可以快速恢复。

性能优化经验

在生产环境中,性能是我们最关注的问题。我们做了很多优化,总结了几个有效的方法。

第一个优化是,查询参数调优。

查询的时候,有几个关键参数:

  • topK:返回多少个结果。不是越多越好,太多了会增加延迟,也会引入噪声。我们一般设为5-10。
  • nprobe(IVF)/ ef(HNSW):搜索范围。越大准确率越高,但延迟也越高。我们在准确率和延迟之间找平衡,一般设为适中的值。
  • 超时时间:设置合理的超时时间,避免慢查询拖垮整个系统。

第二个优化是,缓存。

对于高频查询,我们加了缓存层。相同的查询直接返回缓存结果,不用每次都查向量数据库。我们用Redis做缓存,命中率能到30%左右,大大降低了向量数据库的压力。

第三个优化是,读写分离。

我们把向量数据库的查询节点和写入节点分开。查询节点负责处理查询请求,写入节点负责数据导入。这样,写入操作不会影响查询性能。

第四个优化是,水平扩展。

当单节点的性能不够的时候,我们通过增加查询节点来水平扩展。Milvus支持查询节点的水平扩展,增加节点就能提升查询吞吐量。

第五个优化是,预计算和预热。

对于一些固定的查询模式,我们会预计算结果并缓存。系统启动的时候,会做一些预热查询,让索引加载到内存中,避免第一次查询的冷启动延迟。

踩过的坑

最后,说说我们踩过的几个印象深刻的坑。

第一个坑是,内存不足导致OOM。

HNSW索引很吃内存,我们一开始没有预估好内存,结果数据量上来之后,服务器内存不够用,频繁OOM(内存溢出)。后来我们升级了服务器内存,并且优化了索引参数,才解决这个问题。

建议:上线之前,一定要根据数据量和索引类型,预估好内存需求,留足余量。

第二个坑是,删除数据不释放空间。

很多向量数据库,删除数据之后,磁盘空间不会立刻释放,需要手动compact(压缩)。我们一开始不知道,删除了一批数据之后,磁盘空间没降,还以为删除失败了。后来定期做compact,才解决这个问题。

第三个坑是,embedding模型升级导致向量不兼容。

我们升级了一次embedding模型,新版本的向量维度和旧版本不一样,导致新旧向量不能一起搜索。最后不得不把所有数据重新用新模型生成向量,重建了整个索引,花了好几天时间。

建议:embedding模型的版本要和向量数据绑定,升级模型的时候,要考虑数据迁移的成本。

第四个坑是,查询结果不稳定。

有一段时间,我们发现同一个查询,每次返回的结果不太一样。排查了很久,最后发现是因为索引参数设置不合理,加上并发查询的影响。调整了索引参数和查询参数之后,结果就稳定了。

第五个坑是,监控缺失。

一开始我们没有完善的监控,出了问题只能靠猜。后来我们加了监控,包括查询延迟、吞吐量、内存使用、磁盘使用、索引状态等指标,出了问题能快速定位。

一些建议

给准备在生产环境使用向量数据库的朋友几个建议。

第一,从小做起。不要一开始就上最复杂的方案,先用简单的方案(比如pgvector)跑起来,验证业务价值。等数据量和性能要求上来了,再考虑迁移到更专业的向量数据库。

第二,做好评估。在选型之前,用自己的真实数据做性能测试,看看不同的向量数据库在你的场景下表现如何。不要只看官方的benchmark,因为数据和查询模式不同,结果可能差异很大。

第三,重视数据质量。向量数据库只是工具,数据质量才是关键。花时间在文本预处理、分块策略、embedding模型选择上,比折腾数据库参数更有价值。

第四,完善监控和告警。生产系统一定要有监控,关键指标包括:查询延迟、吞吐量、错误率、内存、磁盘、索引状态。设置告警,出了问题第一时间知道。

第五,有回滚方案。向量数据库的操作(比如重建索引、升级版本)有风险,一定要有回滚方案。重要操作之前,先备份数据。

第六,保持学习。向量数据库是一个快速发展的领域,新技术、新版本、新功能不断出现。保持关注,持续学习,才能用好这个工具。

写在最后

向量数据库是AI时代的重要基础设施,它让大规模的语义检索成为可能。但它也是一个相对年轻的技术,还有很多不成熟的地方,需要我们在实践中不断探索和总结。

我们团队的这些经验,是在踩了无数坑之后总结出来的。希望能帮助正在使用或者准备使用向量数据库的朋友,少走一些弯路。

技术在不断进步,最佳实践也在不断更新。重要的不是记住这些具体的经验,而是建立起一套评估、测试、监控、优化的方法论,这样不管技术怎么变,都能应对自如。

如果你也有向量数据库的使用经验,欢迎在评论区交流。