摘要
检索增强生成(Retrieval-Augmented Generation,RAG)技术已成为大语言模型应用落地的核心架构模式。在RAG系统中,向量数据库承担着语义检索的关键职责,其选型直接影响系统的检索精度、响应延迟和扩展能力。本文将从技术架构、性能特征、适用场景等维度,对DuckDB、Milvus和SurrealDB三款数据库在RAG应用中的表现进行系统性对比分析,为技术选型提供参考依据。
1. RAG技术架构与数据库需求
1.1 RAG工作流程
RAG系统的典型工作流程包含以下环节:
1.2 数据库核心需求
RAG应用对数据库提出了多维度的技术要求:
| 向量检索 | 支持高维向量的相似度计算(余弦、欧氏距离等) |
| 检索性能 | 大规模向量集合下的低延迟查询 |
| 混合查询 | 向量检索与标量过滤的组合能力 |
| 扩展性 | 数据量增长时的水平扩展能力 |
| 元数据管理 | 文档属性、权限等结构化数据的存储与查询 |
2. 数据库技术定位对比
2.1 核心定位差异
三款数据库在设计理念和技术定位上存在本质差异:
| DuckDB | 嵌入式OLAP数据库 | 高性能分析查询 | MIT |
| Milvus | 专用向量数据库 | 大规模向量相似度检索 | Apache 2.0 |
| SurrealDB | 多模型数据库 | 文档、图、向量一体化 | BSL 1.1 |
2.2 架构特征对比
DuckDB架构特征
DuckDB采用进程内嵌入式架构,其核心特征包括:
- 列式存储引擎:针对分析型查询优化的存储格式
- 向量化执行:批量数据处理,充分利用CPU缓存和SIMD指令
- 零外部依赖:单一库文件,无需独立服务进程
- SQL标准兼容:提供丰富的SQL方言支持
Milvus架构特征
Milvus采用分布式云原生架构,核心组件包括:
- 存算分离:计算节点与存储节点独立扩展
- 多级索引:支持HNSW、IVF_FLAT、IVF_PQ、ANNOY等多种ANN索引
- 分片机制:数据自动分片,支持水平扩展
- 依赖组件:etcd(元数据)、MinIO/S3(对象存储)、Pulsar/Kafka(消息队列)
SurrealDB架构特征
SurrealDB采用多模型统一架构:
- 多模型支持:文档存储、图数据库、向量检索三位一体
- 实时能力:内置WebSocket支持,数据变更实时推送
- 单体部署:单一二进制文件,支持嵌入式和服务器模式
- SurrealQL:自研查询语言,融合SQL与图查询语法
3. RAG场景能力详细对比
3.1 向量检索能力
DuckDB向量检索
DuckDB通过内置数组函数提供基础向量检索能力:
— DuckDB向量相似度查询
SELECT
doc_id,
content,
list_cosine_similarity(embedding, $query_embedding) AS similarity_score
FROM documents
ORDER BY similarity_score DESC
LIMIT 10;
技术特点分析:
- 采用暴力搜索(Brute-Force)方式,精确度高
- 缺乏专业ANN索引支持,大规模数据性能受限
- 向量维度和数据规模受内存限制
Milvus向量检索
Milvus提供专业级向量检索能力:
from pymilvus import Collection, connections
connections.connect(host="localhost", port="19530")
collection = Collection("rag_documents")
search_params = {
"metric_type": "COSINE",
"params": {"nprobe": 16}
}
results = collection.search(
data=[query_embedding],
anns_field="embedding",
param=search_params,
limit=10,
expr="category == 'technical' AND publish_date > '2024-01-01'",
output_fields=["doc_id", "content", "metadata"]
)
技术特点分析:
- 支持多种ANN索引算法,可根据场景选择精度与性能的平衡点
- 原生支持向量检索与标量过滤的混合查询
- 亿级向量规模下仍可保持毫秒级响应
SurrealDB向量检索
SurrealDB通过内置向量函数提供检索能力:
— SurrealDB向量检索
SELECT
id,
content,
vector::similarity::cosine(embedding, $query_vec) AS score
FROM document
WHERE score > 0.7
ORDER BY score DESC
LIMIT 10;
技术特点分析:
- 向量检索与文档、图查询统一在同一查询语言中
- 支持基础的向量相似度计算
- 索引能力相对有限,大规模场景性能待验证
3.2 混合查询能力
RAG应用通常需要结合语义检索与结构化过滤,三款数据库的混合查询能力存在显著差异。
DuckDB混合查询
— DuckDB混合查询:向量检索 + 关系型过滤 + 聚合分析
WITH semantic_matches AS (
SELECT
doc_id,
content,
category,
list_cosine_similarity(embedding, $query_vec) AS score
FROM documents
WHERE publish_date >= '2024-01-01'
AND status = 'published'
)
SELECT
category,
COUNT(*) AS match_count,
AVG(score) AS avg_relevance,
ARRAY_AGG(content ORDER BY score DESC)[1:3] AS top_contents
FROM semantic_matches
WHERE score > 0.6
GROUP BY category
ORDER BY avg_relevance DESC;
DuckDB在复杂SQL查询方面具有显著优势,支持窗口函数、CTE、子查询等高级特性。
Milvus混合查询
# Milvus混合查询:向量检索 + 标量过滤
results = collection.search(
data=[query_embedding],
anns_field="embedding",
param={"metric_type": "COSINE", "params": {"nprobe": 10}},
limit=20,
expr="""
category in ['tech', 'science']
AND word_count > 500
AND publish_date > '2024-01-01'
""",
output_fields=["doc_id", "content", "category", "publish_date"]
)
Milvus的标量过滤能力相对基础,不支持复杂的JOIN和聚合操作。
SurrealDB混合查询
— SurrealDB混合查询:向量 + 图遍历
SELECT
id,
content,
vector::similarity::cosine(embedding, $query_vec) AS score,
–>cites–>document.title AS cited_documents,
<–written_by<–author.name AS authors
FROM document
WHERE score > 0.7
AND –>belongs_to–>category.name = 'Machine Learning'
ORDER BY score DESC
LIMIT 10;
SurrealDB的独特优势在于将向量检索与图遍历查询无缝结合。
3.3 扩展性与部署模式
| 部署模式 | 嵌入式/单机 | 分布式集群 | 单机/集群 |
| 水平扩展 | 不支持 | 原生支持 | 有限支持 |
| 高可用 | 不支持 | 支持(多副本) | 支持(TiKV后端) |
| 部署复杂度 | 极低 | 较高 | 中等 |
| 资源占用 | 极低 | 较高 | 中等 |
3.4 生态集成能力
DuckDB生态集成
import duckdb
import pandas as pd
from sentence_transformers import SentenceTransformer
# 与Python数据科学生态无缝集成
model = SentenceTransformer('all-MiniLM-L6-v2')
df = pd.read_parquet('documents.parquet')
df['embedding'] = df['content'].apply(lambda x: model.encode(x).tolist())
# 直接查询DataFrame
conn = duckdb.connect()
results = conn.execute("""
SELECT content, list_cosine_similarity(embedding, ?) AS score
FROM df
ORDER BY score DESC LIMIT 10
""", [query_embedding]).fetchdf()
Milvus生态集成
from langchain.vectorstores import Milvus
from langchain.embeddings import OpenAIEmbeddings
# LangChain原生集成
vectorstore = Milvus.from_documents(
documents,
OpenAIEmbeddings(),
connection_args={"host": "localhost", "port": "19530"},
collection_name="langchain_docs"
)
# 检索器接口
retriever = vectorstore.as_retriever(search_kwargs={"k": 5})
SurrealDB生态集成
from surrealdb import Surreal
async with Surreal("ws://localhost:8000/rpc") as db:
await db.signin({"user": "root", "pass": "root"})
await db.use("namespace", "database")
# 插入带向量的文档
await db.create("document", {
"content": "RAG技术文档",
"embedding": embedding_vector,
"metadata": {"category": "tech"}
})
4. 典型应用场景推荐
4.1 DuckDB适用场景
推荐场景:
- 原型开发与概念验证(POC)阶段
- 文档规模在10万条以内的小型RAG应用
- 需要复杂SQL分析的混合查询场景
- 边缘设备或离线环境部署
- 数据科学工作流中的临时向量检索需求
典型用例:
# 本地知识库问答原型
import duckdb
def simple_rag_query(question: str, conn: duckdb.DuckDBPyConnection):
query_embedding = embed_model.encode(question)
results = conn.execute("""
SELECT content, metadata
FROM knowledge_base
WHERE list_cosine_similarity(embedding, ?) > 0.7
ORDER BY list_cosine_similarity(embedding, ?) DESC
LIMIT 5
""", [query_embedding, query_embedding]).fetchall()
context = "\\n".join([r[0] for r in results])
return llm.generate(f"基于以下内容回答问题:\\n{context}\\n\\n问题:{question}")
4.2 Milvus适用场景
推荐场景:
- 生产级大规模RAG系统(百万至亿级文档)
- 对检索延迟有严格要求的实时应用
- 需要水平扩展能力的企业级部署
- 多租户SaaS平台的向量检索服务
- 与LangChain、LlamaIndex等框架深度集成的项目
典型用例:
# 企业级RAG检索服务
from pymilvus import Collection, utility
class ProductionRAGRetriever:
def __init__(self, collection_name: str):
self.collection = Collection(collection_name)
self.collection.load()
def retrieve(self, query_embedding, filters: dict, top_k: int = 10):
expr = self._build_filter_expr(filters)
results = self.collection.search(
data=[query_embedding],
anns_field="embedding",
param={
"metric_type": "COSINE",
"params": {"nprobe": 16, "ef": 64}
},
limit=top_k,
expr=expr,
output_fields=["doc_id", "content", "metadata"]
)
return self._format_results(results)
def _build_filter_expr(self, filters: dict) –> str:
conditions = []
if "tenant_id" in filters:
conditions.append(f"tenant_id == '{filters['tenant_id']}'")
if "category" in filters:
conditions.append(f"category in {filters['category']}")
return " AND ".join(conditions) if conditions else ""
4.3 SurrealDB适用场景
推荐场景:
- 知识图谱增强的RAG应用
- 需要图关系推理的复杂检索场景
- 全栈应用,希望简化技术栈
- 实时协作应用,需要数据变更订阅
- 中小规模应用,追求开发效率
典型用例:
— 知识图谱增强RAG查询
— 检索相关文档并获取关联实体信息
SELECT
doc.id,
doc.content,
vector::similarity::cosine(doc.embedding, $query_vec) AS relevance,
(
SELECT VALUE entity.name
FROM doc–>mentions–>entity
WHERE entity.type = 'Concept'
) AS related_concepts,
(
SELECT VALUE ref.title
FROM doc–>references–>ref
) AS references
FROM document AS doc
WHERE relevance > 0.6
ORDER BY relevance DESC
LIMIT 10;
5. 混合架构方案
在实际生产环境中,单一数据库往往难以满足RAG系统的全部需求。混合架构方案可充分发挥各数据库的优势。
5.1 DuckDB + Milvus混合架构
┌─────────────────────────────────────────────────────────────┐
│ RAG Application │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ DuckDB │ │ Milvus │ │ LLM │ │
│ │ │ │ │ │ │ │
│ │ • 数据预处理 │───▶│ • 向量存储 │───▶│ • 生成回答 │ │
│ │ • 元数据管理 │ │ • 语义检索 │ │ │ │
│ │ • 分析报表 │◀───│ • ANN索引 │ │ │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
职责分工:
- DuckDB:文档预处理、特征工程、元数据管理、分析报表
- Milvus:向量存储、语义检索、相似度计算
5.2 实现示例
import duckdb
from pymilvus import Collection
class HybridRAGSystem:
def __init__(self):
self.duckdb_conn = duckdb.connect('metadata.duckdb')
self.milvus_collection = Collection("documents")
def ingest_documents(self, documents: list):
# DuckDB处理元数据
metadata_df = self._extract_metadata(documents)
self.duckdb_conn.execute(
"INSERT INTO document_metadata SELECT * FROM metadata_df"
)
# Milvus存储向量
vectors = self._generate_embeddings(documents)
self.milvus_collection.insert([
[doc['id'] for doc in documents],
vectors,
[doc['content'] for doc in documents]
])
def hybrid_search(self, query: str, filters: dict):
# Step 1: DuckDB预过滤获取候选文档ID
candidate_ids = self.duckdb_conn.execute("""
SELECT doc_id FROM document_metadata
WHERE category = ? AND publish_date > ?
""", [filters['category'], filters['date']]).fetchall()
# Step 2: Milvus在候选集中进行向量检索
query_embedding = self._embed(query)
id_filter = f"doc_id in {[id[0] for id in candidate_ids]}"
results = self.milvus_collection.search(
data=[query_embedding],
anns_field="embedding",
param={"metric_type": "COSINE"},
limit=10,
expr=id_filter
)
# Step 3: DuckDB补充完整元数据
doc_ids = [hit.id for hit in results[0]]
full_results = self.duckdb_conn.execute("""
SELECT * FROM document_metadata
WHERE doc_id IN (SELECT UNNEST(?))
""", [doc_ids]).fetchdf()
return full_results
6. 选型决策框架
6.1 核心能力对比
| 向量检索 | 暴力搜索,无ANN索引 | 多种ANN索引,亿级支持 | 基础支持 |
| 部署复杂度 | 零依赖,嵌入式 | 需etcd/MinIO等组件 | 单二进制,较简单 |
| 水平扩展 | 不支持 | 原生分布式 | 有限支持 |
| SQL能力 | 完整SQL支持 | 仅标量过滤 | SurrealQL,较完整 |
| 图查询 | 不支持 | 不支持 | 原生支持 |
| 生态成熟度 | 成熟,社区活跃 | 成熟,LangChain等深度集成 | 较新,生态建设中 |
6.2 快速决策指南
开始
│
▼
文档规模是否超过100万?
│
├─ 是 ──▶ 选择 Milvus
│
▼ 否
是否需要图关系查询?
│
├─ 是 ──▶ 选择 SurrealDB
│
▼ 否
是否为原型/POC阶段?
│
├─ 是 ──▶ 选择 DuckDB
│
▼ 否
是否需要复杂SQL分析?
│
├─ 是 ──▶ 选择 DuckDB + Milvus混合架构
│
▼ 否
选择 Milvus(生产环境首选)
7. 总结与建议
7.1 核心结论
三款数据库在RAG应用场景中各具特色:
- DuckDB:以极低的部署成本和强大的SQL能力见长,适合原型开发和小规模应用,但向量检索能力有限
- Milvus:专业向量数据库的代表,在大规模向量检索场景下性能卓越,是生产级RAG系统的首选
- SurrealDB:多模型统一的创新设计,在知识图谱增强RAG场景中具有独特优势
7.2 实践建议
7.3 未来展望
随着RAG技术的持续演进,数据库领域也在快速发展:
- DuckDB正在增强向量检索能力,未来版本可能引入ANN索引支持
- Milvus持续优化混合查询能力,向全功能数据库方向演进
- SurrealDB作为新兴项目,多模型统一的理念具有长期价值
技术选型应结合团队能力、业务需求和长期规划综合考量,避免过度设计,也要为未来扩展预留空间。
参考资源:
- DuckDB官方文档:https://duckdb.org/docs/
- Milvus官方文档:https://milvus.io/docs/
- SurrealDB官方文档:https://surrealdb.com/docs/
- LangChain向量存储集成:https://python.langchain.com/docs/integrations/vectorstores/
网硕互联帮助中心


评论前必须登录!
注册