RAG应用数据库选型:DuckDB、Milvus、SurrealDB深度对比
发布时间:2026/10/20 15:16:24 锦皓数字建站

1. 开头为什么RAG应用选数据库比选大模型还头疼做RAG检索增强生成应用很多人一上来就盯着Embedding模型怎么选、向量维度设多少、Prompt模板怎么写。但真正把系统推到生产环境时最先暴露问题的反而是数据层——存文档的库、存向量的库、存会话状态的库到底要选几个每个库各承担什么职责数据同步怎么做这些问题不提前想清楚后续的检索质量、写入性能、运维成本都会连环踩坑。我在多个RAG项目中用过DuckDB、Milvus和SurrealDB这三款数据库在社区里经常被放在一起比较但深入了解后会发现它们其实是三条不同的技术路线。DuckDB是嵌入式分析型OLAPMilvus是专为向量检索设计的分布式数据库SurrealDB则是多模型数据库试图在一个引擎里同时搞定文档、关系和向量。它们的交集点在于都能处理向量数据但设计目标、使用场景、性能特征和工作原理差异非常大。这篇文章就从RAG应用的实际需求出发对这三者做一次深度对比把选型背后的逻辑讲透。2. RAG应用的数据层到底在存什么很多人在选型时直接跳到“向量数据库对比”这一步但实际上RAG应用的数据层是一个混合存储场景。只有先拆清楚数据需求才能判断什么类型的数据库真正适合。2.1 语料源数据与文本块RAG首先需要一个知识库这部分数据通常是原始文档和经过切分后的文本块。文本块从几百字符到上千字符不等带有文档ID、章节序号、标题、标签、权限等信息。这部分数据的特征是写入后很少修改但量会持续增长并且需要支持按文档、分类、标签等条件做精确查询供调试、审计和局部更新使用。对于这类数据关系型模型或文档模型非常合适需要支持基础的过滤条件组合查询例如“找到某个批次导入的所有文档分块”“删除某个用户上传的全部文本块”等操作。如果就存几万条文本块任意一款数据库都能应付但如果到了百万级就必须考虑查询效率了。2.2 向量索引与距离计算这是向量数据库的主场。文本块经过Embedding后变成高维向量常见的是768维或1024维浮点数组。检索时需要通过相似度计算找到最相关的向量本质上是大规模高维空间下的最近邻搜索。这一层最核心的指标是召回率、查询延迟和索引构建耗时。不同的库在这三项指标上的取舍差异巨大。DuckDB走的是暴力精准扫描路线Milvus采用的是HNSW、IVF等近似最近邻算法SurrealDB也在较新版本中加入了向量索引支持。只看单条查询延迟的话近似算法会远快于暴力扫描但召回率会打折而暴力扫描在数据量不大、查询并发不高时延迟其实也可接受关键是你要知道自己能容忍多快的查询。2.3 会话状态、用户数据与系统元数据RAG应用不只是“查文档”它还需要维护对话历史、收藏记录、用户反馈、用量统计等状态数据。这部分数据的特征是读写频繁、结构各异、单条数据量小、与用户ID强关联。这类场景里关系型数据库和文档数据库都做得很好但向量数据库普遍不擅长。这也是为什么很多RAG项目最终会做成“组合架构”而不是把全部数据塞进一个库——向量库专注做相似度检索关系库或文档库负责用户数据和会话管理。3. 三个参赛选手的能力画像3.1 DuckDB被低估的嵌入式英雄DuckDB在RAG选型讨论中亮相很多人会觉得意外。毕竟它的定位是嵌入式OLAP数据库主打的是分析型工作负载比如跑聚合、做联表、统计指标。但它有一个杀手级特性原生支持向量搜索所需的距离函数可以在SQL里直接完成向量相似度计算。DuckDB还支持加载社区扩展其中就包含向量相似度计算的函数库可以直接写SQL查询。对于百万级以下的数据量DuckDB的暴力扫描性能足够好而且它没有独立服务端进程直接嵌入到Python应用中这在原型阶段优势太明显了。数据集是几万条文档块时我实测过召回率100%单条查询延迟也在几十毫秒以内。但DuckDB的短板也很明显。它不是为高并发而生的设计目标是单机处理分析查询不适合作为面向大量客户端并发写入和查询的服务端数据库写入方式偏向批量不适合高频小规模更新。如果RAG应用要直接暴露给终端用户DuckDB无法作为独立服务支撑在线业务。3.2 Milvus更专业的向量搜索引擎Milvus的设计思路就是“把向量检索做到极致”。它采用分布式架构内置多种索引类型支持混合查询——就是同时过滤结构化属性和向量相似度还提供了完整的SDK、监控体系和水平扩展能力。在生产级RAG服务中Milvus通常被用作召回引擎。Milvus的数据模型围绕“集合”和“字段”组织每个向量是一个实体除了向量字段外可以附带动态字段或标量字段。构建索引时会有明确的构建时间和内存占用查询时可以指定过滤表达式来缩小范围。它是真正的“为向量服务设计的数据库”。代价是运维复杂度明显更高。跑一个单机版还好一旦上集群就涉及协调节点、数据节点、查询节点和对象存储的配置管理。数据量不大时Milvus的分布式优势完全发挥不出来反而白白增加了部署成本和学习成本。3.3 SurrealDB多模型数据库的多面手SurrealDB是这三者中最“年轻”的一个。它把关系表、文档结构和图关系整合在一个引擎里也支持向量类型和索引。设计理念是一个数据库就够了场景切换不需要换引擎。在实际体验中SurrealDB的SurrealQL语法和传统SQL差异很大需要花时间适应。它的REST API、实时通知Live Queries、权限控制体系非常完善这在生产环境中很实用。向量索引引入后可以直接在记录上存向量字段在同一套查询里完成文本属性过滤和相似度排序避免了多库拼装的复杂逻辑。不过要客观说SurrealDB的向量检索能力在成熟度上还赶不上Milvus。索引类型相对单一大规模向量场景下的调优空间有限。它更适合中小规模、业务逻辑复杂的应用一个库管所有状态和检索省去了多系统的同步成本。4. 选型评测维度与实测思路选定数据库不能只看技术热度要回到三个核心维度性能表现、功能边界、运维成本。以下是我在对比三款产品时使用的评测框架。4.1 性能指标怎么测才有效评测向量数据库时最忌直接用随机生成的高维向量来跑基准测试因为真实文本向量的分布特征和你随意生成的向量分布差异很大。我自己踩过这个坑早期某个项目用随机向量测出来延迟很低换成了真实文本的嵌入向量后查询延迟出现了数倍波动。所以评测时固定使用同一套真实文本数据集并统一Embedding模型才谈得上对比的公平性。针对DuckDB、Milvus、SurrealDB我重点测了四个指标批量导入耗时写入1万条、10万条、50万条文本块观察导入总耗时和资源占用索引构建时间Milvus构建HNSW索引、SurrealDB构建向量索引的时间差异P95单条查询延迟在固定并发下打压力度观察延迟分布混合过滤向量检索延迟在带标签过滤条件和无过滤两种情况下分别测试。结果比较有意思。10万条以内DuckDB依靠暴力扫描查询延迟稳定在20到80毫秒之间波动和构建了索引的Milvus差距不算大到了50万条以上Milvus的HNSW优势就体现出来了延迟在10毫秒以内而DuckDB的暴力扫描性能随着数据量增长明显退化。SurrealDB在查询延迟上比DuckDB略高功能上更灵活但索引参数调优不像Milvus那么精细。4.2 功能边界对比列一个表会更直观维度DuckDBMilvusSurrealDB部署形态嵌入式无独立服务独立服务可集群独立服务可嵌入数据模型关系型表结构集合字段多模型表文档图向量索引类型无独立索引靠暴力扫描HNSW、IVF等自研向量索引选项较少混合查询能力SQL天然支持但无索引加速支持标量过滤向量检索支持记录属性向量相似度高并发支持弱设计面向分析场景强面向在线服务中等适合中小规模在线场景运维复杂度极低pip install即可中等偏高中等这张表透露了一个关键信息这三款产品并没有落在完全同一的赛道里。DuckDB和SurrealDB在中小规模场景下是直接竞争对手Milvus更偏向大规模在线检索场景。选型时先确认自己的数据规模和并发量级再谈哪个好。5. 典型RAG场景下的方案组合与取舍5.1 轻量级原型阶段DuckDB是最佳搭档个人做项目原型、内部知识库Demo或数据处理脚本时我强烈推荐DuckDB。原因非常直接安装一条pip命令就能完成无需启动服务无需担心网络端口和权限配置所有数据落在本地文件里备份就是把文件拷贝一份。原型阶段迭代快文档重切、Embedding重跑、数据清理是常规操作DuckDB用SQL语句就能完成复杂的数据变换比在向量数据库里折腾省事太多。我做过一个文档问答原型数据量2万条文本块DuckDB查询延迟保持在80毫秒内加上大模型推理时间整体响应在可接受范围。后面分享给几个同事做内测时DuckDB暴露出并发短板——多人同时查询时延迟明显上升。这里的关键心得是DuckDB解决的是“单机分析原型验证”的问题如果项目有清晰的上线预期那么从一开始就要预留迁移路径代码中将对数据库的操作封装到独立的仓储层避免SQL语句散落各处。后期无论换Milvus还是SurrealDB都能平滑迁移。5.2 生产级在线检索Milvus的成熟优势当RAG应用要面向外部用户提供在线问答服务数据量达到百万级、查询并发几十甚至上百时Milvus是更稳妥的选择。它的成熟度体现在工程细节上索引参数多样可以根据数据分布调整M、efConstruction、efSearch等参数支持多副本和水平扩展有Prometheus监控指标SDK覆盖Python、Java、Go等主流语言。Milvus的混合查询能力在实际RAG场景中价值很大。比如一家企业有不同部门的文档用户可以指定只看某一部门的资料这时查询会附加过滤条件。Milvus会借助标量索引先做过滤再做向量检索既保证准确性又不会让延迟劣化得太严重。但Milvus不适合当全能存储存在。会话记录、用户反馈、用量统计这类数据放进去既浪费存储空间又会增加集合管理的复杂度。生产架构中我通常把它和一台简洁的PostgreSQL搭配使用——Milvus管向量召回PostgreSQL管业务状态两者通过应用代码协调。5.3 多租户业务逻辑复杂SurrealDB的用武之地SurrealDB更适合业务逻辑复杂、数据关联密集的中小型应用。假设你在做一个面向多个团队的知识库平台需要为每个团队隔离数据、记录团队成员关系、保存文档元数据和向量数据SurrealDB的单库搞定能力就非常有吸引力了。我试用SurrealDB时最大的感受是它的权限体系和RLive Query对应用开发太友好了。权限规则可以精细到每一条记录前端可以直接订阅实时更新客户端通过WebSocket拿数据省掉了自己写同步层的步骤。这意味着后端代码量能大幅减少。需要注意的问题是SurrealDB的向量检索能力有待更多项目验证。我在测试中发现数据量超过10万条后索引参数对查询质量影响明显可调参数少社区经验也不像Milvus那样丰富。所以如果核心场景是超大规模召回我建议慎重选择SurrealDB如果业务属性重、检索量有限它的综合效率反而较高。5.4 三种组合架构的实战建议根据项目规模和应用形态我总结出三套组合架构可以直接作为选型参考第一种轻量内部工具。DuckDB单库存文本块和向量层元数据用SQL查询大模型调用外部API。适合查询量低、纯内部使用、没有用户体系的场景。优点是开发和部署成本极低DuckDB的数据文件可以直接离线分享冷备份也很省心。第二种标准在线RAG服务。Milvus做向量召回PostgreSQL或MySQL存用户和会话数据两者配合。适合对外提供产品化服务对查询延迟和数据一致性有明确要求。数据管道中用DuckDB做预处理和批量分析可以充分利用其数据处理速度。第三种多租户应用平台。SurrealDB作为主数据库既管业务实体和关系也存向量数据用权限体系隔离租户数据。适合功能复杂、数据关联多、团队规模有限的项目。6. 实操中容易踩的坑6.1 向量维度与距离算法一致性这是最隐蔽的坑。Embedding时你用的是OpenAI的三千维接口那存储和检索时的距离函数就必须匹配。向量数据库中相似度计算通常有内积、余弦相似度、欧氏距离三种选错距离函数会导致检索结果与实验阶段不一致。DuckDB中自己要写清楚距离逻辑Milvus中建Collection时就要指定metric typeSurrealDB的向量函数同样要显式声明。任何一步不一致结果都会莫名其妙地偏差。6.2 Milvus Collection设计与动态字段Milvus的数据模型是先定义schema后写入数据字段一旦建好就很难调整。如果你要把文档标题、来源、权限等属性作为过滤条件字段在一开始就要设计好schema。一个常见优化手段是用动态字段Dynamic Field存储额外元数据避免为每个新属性重建集合。但注意动态字段不能直接参与过滤那会造成查询性能降低。实测下来为高频过滤字段单独建标量索引查询体验提升非常明显。6.3 DuckDB高并发时当作服务使用DuckDB的文档明确说它不适合高并发服务场景。但实际项目中总有团队图省事直接用FastAPI包一层把DuckDB当在线服务数据库来跑。小流量下问题不大流量一旦上来锁竞争和内存占用会直线拉升。我在一个项目里被这种用法坑过。解决方案是强制增加缓存层、降低查询频率或者干脆迁移到独立数据库服务。6.4 生产环境监控和可观测性RAG应用的数据库层监控常常被忽视。Milvus有Dashboard可以看到查询延迟和索引状态DuckDB把状态暴露在进程内部需要手动采集SurrealDB提供系统表但文档不够详细。上线前务必把CPU、内存、磁盘、查询延迟、错误率等指标接入监控系统。生产环境上因为索引构建导致CPU飙高进而拖垮整个服务的案例我见得太多了。7. 我现在的选择方式项目还在原型阶段时我的默认选择始终是DuckDB加Python包快速验证检索效果和整体链路。确定业务规模后我会做一个快速评估给未来半年的数据量乘以查询并发量估值如果数据量在百万以下、并发低SurrealDB整套方案能极大简化架构如果数据量大或并发要求高就用Milvus承担向量检索让更传统的数据库负责业务状态。选型没有绝对的“最好”关键是你对数据库特性的认知是否匹配业务需求。把DuckDB当分析工具、Milvus当检索引擎、SurrealDB当业务数据底座三者各归其位RAG应用的数据层会清爽很多。希望这篇文章能帮你避开我踩过的坑。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。