终于明白,快乐是选择,不是结果。
而真正的快乐是一种当下的能力:在阴天选择看见云层的纹路,在人群中选择听见自己的心跳。它不依附于任何条件,只是内心角度的转动。
摘要:RAG(检索增强生成)应用的核心瓶颈在于"召回质量"——如何在海量数据中精准找到与大模型提问最相关的知识片段。单一检索路径(纯向量或纯关键词)往往顾此失彼:向量检索擅长语义相似但可能漏掉关键属性约束,关键词检索精确但无法理解同义词和语义变体。达梦DM9通过"关系+全文+向量"三路并行召回,将精确条件匹配、关键词检索与语义检索融为一体,配合查询优化器的智能调度,在单次SQL中完成多路召回与融合排序。本文从RAG召回原理、DM9混合检索架构、实战SQL实现三个维度,深度解析如何用一条SQL构建企业级RAG检索引擎。
大模型应用落地的核心挑战之一,是如何让模型"说对话"——不 hallucinate(幻觉)、不胡编乱造。RAG(Retrieval-Augmented Generation,检索增强生成)是目前最主流的解决方案:用户提问时,先从知识库中检索相关知识,再将检索结果注入Prompt,引导大模型基于事实生成回答。
然而,RAG的召回环节存在一个根本性矛盾:
纯向量检索的问题:
纯关键词检索的问题:
多路召回的价值:同时从"精确条件、关键词匹配、语义相似"三个维度召回候选,取并集后融合排序,兼顾精确性和语义理解能力。
达梦DM9的破局方案是:在一个SQL查询中,同时执行关系型过滤、全文检索和向量相似度计算,由查询优化器自动选择最优执行路径。
传统RAG架构需要多套系统拼凑:向量数据库负责语义检索,关系数据库负责属性过滤,搜索引擎负责关键词匹配。应用层需要分别调用三个系统,再手动合并结果。这种架构的问题在于数据同步延迟、跨系统调用开销大、结果合并复杂。
DM9 RAG架构则完全不同:用户提问后,Embedding模型生成查询向量,同时关系条件和全文关键词作为过滤条件,所有信息在DM9单库中通过一条SQL完成三路召回,天然具备ACID一致性。
| 召回路径 | 技术实现 | 核心能力 | 适用场景 |
|---|---|---|---|
| 精确召回 | B+树索引 + WHERE条件 | 结构化属性精确过滤 | 时间范围、分类、状态、ID |
| 关键词召回 | GIN全文索引 + tsquery | 关键词匹配、短语检索 | 产品名称、文档标题、标签 |
| 语义召回 | HNSW向量索引 + 余弦距离 | 语义相似度、同义词理解 | 概念相似、语义相近、以图搜图 |
三条路径共享同一套事务引擎,查询结果天然一致,无需担心数据同步问题。
精确召回基于关系型数据库的B+树索引,通过WHERE条件对结构化属性进行精确过滤。这是三路召回中效率最高的一条路径,通常在毫秒级完成。
B+树索引将数据按主键或索引键有序组织,查询时通过树形结构快速定位目标数据,时间复杂度为O(log N)。对于范围查询(BETWEEN、>、<)和等值查询(=),B+树索引能提供极高的查询效率。
-- 场景:在"技术规范"分类中,找出2026年发布的文档
SELECT doc_id, title, content
FROM knowledge_base
WHERE doc_type = '技术规范' -- 精确匹配:文档类型
AND create_time >= '2026-01-01' -- 范围过滤:创建时间
AND create_time < '2027-01-01'
AND status = '已发布' -- 状态过滤
AND department = '架构部'; -- 部门过滤
-- 执行计划:B+树索引快速定位
-- Index Scan using idx_doc_type on knowledge_base
-- Index Cond: doc_type = '技术规范'
-- Filter: (create_time >= '2026-01-01') AND (status = '已发布')
-- 复合索引:按查询频率最高的列在前排序
CREATE INDEX idx_kb_filter ON knowledge_base(doc_type, status, department, create_time);
-- 分区表:按时间分区,加速范围查询
CREATE TABLE knowledge_base (
doc_id INT PRIMARY KEY,
title VARCHAR(500),
content TEXT,
doc_type VARCHAR(50),
create_time TIMESTAMP,
status VARCHAR(20),
department VARCHAR(50)
) PARTITION BY RANGE (create_time) (
PARTITION p2024 VALUES LESS THAN ('2025-01-01'),
PARTITION p2025 VALUES LESS THAN ('2026-01-01'),
PARTITION p2026 VALUES LESS THAN ('2027-01-01')
);
DM9的全文检索基于GIN(Generalized Inverted Index,通用倒排索引),将文档内容分词后建立倒排列表。查询时,将查询词分词后在倒排列表中查找包含这些词的文档,返回匹配结果。
-- 创建全文检索索引(中文分词)
CREATE INDEX idx_kb_fulltext ON knowledge_base
USING gin(to_tsvector('chinese', title || ' ' || content));
-- 关键词召回查询
SELECT doc_id, title,
ts_rank(to_tsvector('chinese', title || ' ' || content),
plainto_tsquery('chinese', '数据库 容灾')) AS rank
FROM knowledge_base
WHERE to_tsvector('chinese', title || ' ' || content)
@@ plainto_tsquery('chinese', '数据库 容灾')
ORDER BY rank DESC
LIMIT 20;
DM9全文检索支持短语匹配、逻辑组合和权重设置。例如,短语匹配可精确匹配"数据安全"这个短语;逻辑组合可实现包含"数据库"且包含"容灾"但不包含"Oracle"的复杂查询;权重设置可让标题匹配的权重高于内容匹配。
向量语义检索将文本转换为高维向量(通常768维或更高),通过计算向量间的余弦相似度来衡量语义相似度。HNSW(Hierarchical Navigable Small World)索引通过构建多层图结构,将O(N)的暴力搜索优化到O(log N)。
-- 创建向量表
CREATE TABLE doc_embeddings (
doc_id INT PRIMARY KEY,
embedding VECTOR(768)
);
-- 创建HNSW索引
CREATE INDEX idx_doc_hnsw ON doc_embeddings
USING hnsw (embedding vector_cosine_ops) WITH (m = 16);
-- 语义召回:找出与查询语义最相似的Top-10文档
SELECT d.doc_id, kb.title,
cosine_distance(d.embedding, query_vec) AS distance
FROM doc_embeddings d,
(SELECT vector_from_text('数据库容灾方案') AS query_vec) q,
knowledge_base kb
WHERE d.doc_id = kb.doc_id
ORDER BY d.embedding <=> query_vec
LIMIT 10;
三路召回的结果需要融合排序。常见的融合策略包括:
| 融合策略 | 公式 | 适用场景 |
|---|---|---|
| 加权求和 | score = w1×精确 + w2×关键词 + w3×语义 | 通用场景,权重可调 |
| 倒数排名融合(RRF) | score = Σ 1/(k + rank_i) | 多路结果排名差异大 |
| 最大值归一化 | score = max(score_i) | 突出单路最佳结果 |
-- 场景:在"技术规范"分类中,搜索与"数据库容灾"相关的文档
WITH
-- 查询向量和关键词
query_params AS (
SELECT
vector_from_text('数据库容灾方案') AS query_vec,
plainto_tsquery('chinese', '数据库 容灾') AS query_ts
),
-- 路径1:精确召回(结构化过滤)
exact_recall AS (
SELECT
kb.doc_id,
kb.title,
kb.content,
1.0 AS exact_score
FROM knowledge_base kb, query_params qp
WHERE kb.doc_type = '技术规范'
AND kb.status = '已发布'
AND kb.create_time >= '2026-01-01'
),
-- 路径2:关键词召回(全文检索)
keyword_recall AS (
SELECT
kb.doc_id,
kb.title,
kb.content,
ts_rank(
to_tsvector('chinese', kb.title || ' ' || kb.content),
qp.query_ts
) AS keyword_score
FROM knowledge_base kb, query_params qp
WHERE to_tsvector('chinese', kb.title || ' ' || kb.content) @@ qp.query_ts
),
-- 路径3:语义召回(向量相似度)
semantic_recall AS (
SELECT
d.doc_id,
kb.title,
kb.content,
(1 - cosine_distance(d.embedding, qp.query_vec)) AS semantic_score
FROM doc_embeddings d
JOIN knowledge_base kb ON d.doc_id = kb.doc_id
CROSS JOIN query_params qp
ORDER BY d.embedding <=> qp.query_vec
LIMIT 50
)
-- 融合三路召回结果
SELECT
COALESCE(e.doc_id, k.doc_id, s.doc_id) AS doc_id,
COALESCE(e.title, k.title, s.title) AS title,
LEFT(COALESCE(e.content, k.content, s.content), 200) AS content_preview,
-- 加权融合分数(可调整权重)
COALESCE(e.exact_score, 0) * 0.3 +
COALESCE(k.keyword_score, 0) * 0.3 +
COALESCE(s.semantic_score, 0) * 0.4 AS fusion_score
FROM exact_recall e
FULL OUTER JOIN keyword_recall k ON e.doc_id = k.doc_id
FULL OUTER JOIN semantic_recall s ON COALESCE(e.doc_id, k.doc_id) = s.doc_id
ORDER BY fusion_score DESC
LIMIT 10;
DM9的查询优化器会自动选择最优执行计划:
-- 查看执行计划
EXPLAIN ANALYZE
SELECT ...
FROM knowledge_base kb
WHERE kb.doc_type = '技术规范' -- B+树索引
AND to_tsvector('chinese', kb.content) -- GIN全文索引
@@ plainto_tsquery('chinese', '数据库容灾')
ORDER BY kb.embedding <=> query_vec -- HNSW向量索引
LIMIT 10;
-- 执行计划关键信息:
-- Limit (cost=100.00..120.50 rows=10)
-- -> Sort (cost=100.00..110.00 rows=1000)
-- Sort Key: (embedding <=> query_vec)
-- -> BitmapAnd
-- -> Bitmap Index Scan using idx_doc_type -- B+树
-- -> Bitmap Index Scan using idx_kb_fulltext -- GIN
-- -> Index Scan using idx_doc_hnsw -- HNSW
-- 知识库主表
CREATE TABLE enterprise_kb (
doc_id SERIAL PRIMARY KEY,
title VARCHAR(500),
content TEXT,
author VARCHAR(100),
department VARCHAR(50),
doc_type VARCHAR(30), -- 合同/规范/通知/FAQ
status VARCHAR(20), -- 草稿/已发布/已归档
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
tags JSON, -- {"priority": "high", "project": "AI"}
content_vec VECTOR(768) -- 文本语义向量
);
-- 创建多路召回所需索引
CREATE INDEX idx_kb_type ON enterprise_kb(doc_type);
CREATE INDEX idx_kb_status ON enterprise_kb(status);
CREATE INDEX idx_kb_dept ON enterprise_kb(department);
CREATE INDEX idx_kb_time ON enterprise_kb(create_time);
CREATE INDEX idx_kb_fulltext ON enterprise_kb
USING gin(to_tsvector('chinese', title || ' ' || content));
CREATE INDEX idx_kb_hnsw ON enterprise_kb
USING hnsw (content_vec vector_cosine_ops) WITH (m = 16);
-- 插入知识文档并自动生成向量
INSERT INTO enterprise_kb (title, content, author, department, doc_type, status, content_vec)
VALUES (
'DM9多租户隔离技术规范',
'DM9采用内核级租户隔离机制,通过资源组实现CPU、内存、IO的精细化管控...',
'张三',
'架构部',
'技术规范',
'已发布',
dm9_embedding('DM9多租户隔离技术规范 DM9采用内核级租户隔离机制...')
);
-- 场景:架构部员工搜索"租户资源隔离"相关文档
WITH
query_params AS (
SELECT
vector_from_text('租户资源隔离') AS query_vec,
plainto_tsquery('chinese', '租户 | 隔离 | 资源') AS query_ts
),
-- 精确召回:架构部、已发布、技术规范
exact_recall AS (
SELECT doc_id, title, content, 1.0 AS exact_score
FROM enterprise_kb
WHERE department = '架构部' AND status = '已发布' AND doc_type = '技术规范'
),
-- 关键词召回
keyword_recall AS (
SELECT doc_id, title, content,
ts_rank(to_tsvector('chinese', title || ' ' || content), qp.query_ts) AS keyword_score
FROM enterprise_kb, query_params qp
WHERE to_tsvector('chinese', title || ' ' || content) @@ qp.query_ts
),
-- 语义召回
semantic_recall AS (
SELECT doc_id, title, content,
(1 - cosine_distance(content_vec, qp.query_vec)) AS semantic_score
FROM enterprise_kb, query_params qp
ORDER BY content_vec <=> qp.query_vec
LIMIT 20
)
-- 融合排序
SELECT
COALESCE(e.doc_id, k.doc_id, s.doc_id) AS doc_id,
COALESCE(e.title, k.title, s.title) AS title,
LEFT(COALESCE(e.content, k.content, s.content), 150) AS preview,
COALESCE(e.exact_score, 0) * 0.25 +
COALESCE(k.keyword_score, 0) * 0.35 +
COALESCE(s.semantic_score, 0) * 0.4 AS fusion_score
FROM exact_recall e
FULL OUTER JOIN keyword_recall k USING (doc_id)
FULL OUTER JOIN semantic_recall s USING (doc_id)
ORDER BY fusion_score DESC
LIMIT 5;
-- 复合索引:覆盖多路召回的过滤条件
CREATE INDEX idx_kb_multi ON enterprise_kb(doc_type, status, department, create_time);
-- 分区表:按时间分区加速范围查询
CREATE TABLE enterprise_kb (...) PARTITION BY RANGE (create_time);
-- 向量索引参数调优
CREATE INDEX idx_kb_hnsw ON enterprise_kb
USING hnsw (content_vec vector_cosine_ops)
WITH (m = 32, ef_construction = 200); -- 更高精度,更大内存
-- 设置HNSW搜索宽度(平衡精度和速度)
SET hnsw.ef_search = 100;
-- 设置全文检索的nprobe(平衡召回率和速度)
SET ivfflat.probes = 10;
-- 查看索引使用情况
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read
FROM pg_stat_user_indexes
WHERE tablename = 'enterprise_kb'
ORDER BY idx_scan DESC;
-- 查看慢查询
SELECT query, mean_exec_time, calls
FROM pg_stat_statements
WHERE query LIKE '%enterprise_kb%'
ORDER BY mean_exec_time DESC
LIMIT 10;
达梦DM9的RAG多路召回方案,通过"关系+全文+向量"三路并行召回,解决了单一检索路径的局限性:
核心优势:
随着达梦Fusion AI计划的推进,DM9还将引入库内AI推理、数据语义检索、xPU加速等能力,进一步降低RAG应用的开发和运维门槛。
作者注:本文基于达梦DM9公开技术资料、官方白皮书以及DTCC 2026演讲内容撰写,深入解析了DM9 RAG多路召回的技术原理和实现机制。文中SQL示例基于DM9语法,实际部署请参考官方最新文档。
标签:#达梦数据库 #达梦同行者征文 #DM9 #RAG #多路召回 #混合检索 #向量检索
欢迎 👍点赞✍评论⭐收藏,欢迎指正
文章
阅读量
获赞
