设计一个高效的 RAG(检索增强生成)系统数据库,核心在于厘清"知识库 ➔ 原始文档/条目 ➔ 文本切片(Chunk)"的三层层级结构 ,同时要兼顾向量检索 与传统关系型数据库的解耦与关联。
下面为你梳理标准的设计思路与可直接落地的数据表 DDL(以 PostgreSQL 格式为例,包含常用索引和字段解析)。
一、 整体层级关系与设计思路
┌──────────────┐
│ 知识库表 │ (Knowledge Base)
│ (1) │ 定义隔离粒度、权限、全局检索参数
└──────┬───────┘
│ 1:N
┌──────▼───────┐
│ 知识条目表 │ (Document / Entry)
│ (N) │ 管理原始文件/文章元数据、解析状态、版本控制
└──────┬───────┘
│ 1:N
┌──────▼───────┐
│ 切片表 │ (Chunk)
│ (N) │ 存储切片文本、向量映射ID、上下文关联、元数据 Filter
└──────────────┘
- 知识库表 (
knowledge_base):租户/业务隔离的最上层容器。决定了模型调用时的召回范围(例如"HR部门知识库"或"产品手册知识库")。 - 知识条目表 (
knowledge_entry) :承载具体的文件或文档(如一个 PDF、网页链接或 MarkDown)。关键点在于记录文档的解析和切片状态,以便在异步任务中处理重试和进度通知。 - 切片表 (
knowledge_chunk) :RAG 检索的最小单位。切片不一定要直接存高维向量 (生产环境更建议向量存向量数据库如 Milvus/Pinecone/pgvector,此表存储vector_id以及原始文本与 Token 统计)。
二、 核心数据表设计 (SQL DDL)
1. 知识库表 (knowledge_base)
用于分类和隔离数据,同时配置当前知识库特有的 RAG 参数(如重排模型、默认分片大小)。
sql
CREATE TABLE knowledge_base (
id VARCHAR(36) PRIMARY KEY, -- 知识库ID (UUID)
tenant_id VARCHAR(36) NOT NULL, -- 租户/用户ID (用于多租户隔离)
name VARCHAR(100) NOT NULL, -- 知识库名称
description TEXT, -- 描述
avatar_url VARCHAR(255), -- 关联图标/封面
-- RAG 配置项 (JSON 存储,方便扩展)
rag_config JSONB DEFAULT '{
"embedding_model": "text-embedding-3-small",
"chunk_size": 512,
"chunk_overlap": 50,
"similarity_threshold": 0.75
}'::jsonb,
status VARCHAR(20) DEFAULT 'active', -- 状态: active(正常), disabled(禁用)
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_kb_tenant ON knowledge_base(tenant_id);
2. 知识条目表 (knowledge_entry)
对应一份上传的文件或网页。重点在于记录文件元数据、解析状态及分词/切片统计。
sql
CREATE TABLE knowledge_entry (
id VARCHAR(36) PRIMARY KEY, -- 条目ID
kb_id VARCHAR(36) NOT NULL, -- 归属知识库ID
title VARCHAR(255) NOT NULL, -- 文档标题/文件名
source_type VARCHAR(20) NOT NULL, -- 来源类型: file(文件), url(网页), manual(手动录入)
file_path VARCHAR(500), -- 对象存储路径 (S3/OSS路径)
file_size BIGINT DEFAULT 0, -- 文件大小 (Byte)
file_type VARCHAR(20), -- 文件格式: pdf, md, docx, txt
-- 异步处理与解析状态
parse_status VARCHAR(20) DEFAULT 'pending', -- pending(待处理), parsing(解析中), parsed(完成), failed(失败)
error_message TEXT, -- 解析失败时的日志
-- 统计指标
chunk_count INT DEFAULT 0, -- 生成的切片总数
word_count INT DEFAULT 0, -- 字符/Token数
created_by VARCHAR(36), -- 创建人
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (kb_id) REFERENCES knowledge_base(id) ON DELETE CASCADE
);
CREATE INDEX idx_entry_kb ON knowledge_entry(kb_id);
CREATE INDEX idx_entry_status ON knowledge_entry(parse_status);
3. 切片表 (knowledge_chunk)
RAG 系统中最频繁读取的表,对应检索时召回的文本片段。
sql
CREATE TABLE knowledge_chunk (
id VARCHAR(36) PRIMARY KEY, -- 切片ID
kb_id VARCHAR(36) NOT NULL, -- 知识库ID (预冗余字段,加快速查)
entry_id VARCHAR(36) NOT NULL, -- 归属条目ID
chunk_index INT NOT NULL, -- 切片序号 (例如第 0, 1, 2 个 Chunk,方便排序上下文)
content TEXT NOT NULL, -- 切片的文本内容
token_count INT DEFAULT 0, -- 节点 Token 数量
-- 向量关联与混合检索支持
vector_id VARCHAR(64), -- 向量数据库(Milvus/Qdrant等)中的 Vector ID
-- 上下文扩展 (防止切割时丢失关键信息)
prev_chunk_id VARCHAR(36), -- 前一个切片ID
next_chunk_id VARCHAR(36), -- 后一个切片ID
-- 元数据过滤 (用于 Metadata Filtering,例如自定义标签、分类)
metadata JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (kb_id) REFERENCES knowledge_base(id) ON DELETE CASCADE,
FOREIGN KEY (entry_id) REFERENCES knowledge_entry(id) ON DELETE CASCADE
);
-- 常用查询索引
CREATE INDEX idx_chunk_entry ON knowledge_chunk(entry_id, chunk_index);
CREATE INDEX idx_chunk_kb ON knowledge_chunk(kb_id);
CREATE INDEX idx_chunk_vector ON knowledge_chunk(vector_id);
三、 设计中的关键细节建议
- 预留
kb_id冗余字段
在knowledge_chunk表中冗余kb_id字段,可以在检索时避开与knowledge_entry的复杂 JOIN 查询,大幅提高向量召回后的全文查询与鉴权效率。 - 上下文补偿设计(
prev_chunk_id/next_chunk_id)
当切片检索命中了某个特定 Chunk 时,往往需要将前后的 Chunk 一起丢给大模型(Sliding Window / Parent-Child Chunking 技术),记录前后切片 ID 能极大简化滑动窗口的拼接逻辑。 - 向量储存解耦
- 方案 A(推荐): 关系型数据库只存业务文本与元数据,向量数据存入专业向量数据库(如 Milvus, Qdrant),通过
vector_id关联。 - 方案 B(轻量): 如果数据量较小(小于 100 万级),可直接使用 PostgreSQL 的
pgvector插件,将向量映射字段换为embedding vector(1536)存入knowledge_chunk中。
- JSONB 元数据过滤 (
metadata)
支持灵活添加诸如{"category": "policy", "year": 2024, "access_level": "internal"}等字段,以便在检索时搭配 Hybrid Search(混合检索)进行预过滤或后过滤。