9.1 KiB
9.1 KiB
城市生命线数据库优化方案总结
更新日期:2025-12-02
一、核心优化内容
1. 知识库版本管理(简化方案)
设计原则
- 不创建额外的历史表或快照表
- 直接在现有表中添加版本字段
- 使用乐观锁防止并发编辑冲突
文档表(tb_knowledge_document)新增字段
| 字段名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
version |
INTEGER | 1 | 版本号(整数递增) |
root_doc_id |
VARCHAR(50) | NULL | 根文档ID(版本组标识,首次上传时等于doc_id) |
is_current |
BOOLEAN | true | 是否当前使用的版本 |
索引:
CREATE INDEX idx_doc_root_current
ON knowledge.tb_knowledge_document(root_doc_id, is_current)
WHERE deleted = false;
分段表(tb_knowledge_chunk)新增字段
| 字段名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
version |
INTEGER | 1 | 分段版本号(用于乐观锁,每次编辑+1) |
使用示例
创建新版本:
-- 1. 标记旧版本为非当前
UPDATE knowledge.tb_knowledge_document
SET is_current = false
WHERE root_doc_id = 'root_xxx';
-- 2. 插入新版本
INSERT INTO knowledge.tb_knowledge_document (
doc_id, root_doc_id, version, is_current, ...
) VALUES (
'new_doc_id', 'root_xxx', 2, true, ...
);
编辑分段(乐观锁):
UPDATE knowledge.tb_knowledge_chunk
SET content = '新内容', version = version + 1
WHERE chunk_id = 'xxx' AND version = 1; -- 版本检查
查询当前版本:
SELECT * FROM knowledge.tb_knowledge_document
WHERE root_doc_id = 'root_xxx'
AND is_current = true
AND deleted = false;
二、多服务数据隔离方案
设计原则
- 使用
dept_path实现部门/租户隔离(已有字段) - 添加
service_type实现服务间隔离 - 不使用 tenant_id(dept_path 已足够)
隔离层级
| 隔离级别 | 字段 | 用途 | 示例 |
|---|---|---|---|
| 服务级 | service_type | 区分不同业务服务 | bidding / customer_service / internal |
| 部门级 | dept_path | 区分部门/租户 | /dept1/subdept1/ |
已添加 service_type 的表
| 表名 | 位置 | 说明 |
|---|---|---|
knowledge.tb_knowledge_base |
createTableKnowledge.sql | 知识库 |
knowledge.tb_knowledge_document |
createTableKnowledge.sql | 知识文档 |
file.tb_sys_file |
createTableFile.sql | 文件 |
file.tb_file_relation |
createTableFile.sql | 文件关联 |
message.tb_message |
createTableMessage.sql | 消息 |
message.tb_message_template |
createTableMessage.sql | 消息模板 |
log.tb_sys_log |
createTableLog.sql | 系统日志 |
查询示例
// 招投标服务查询
public List<Document> getBiddingDocuments(String deptPath) {
return documentMapper.selectList(
new QueryWrapper<Document>()
.eq("service_type", "bidding") // 服务隔离
.likeRight("dept_path", deptPath) // 部门隔离
.eq("is_current", true) // 当前版本
.eq("deleted", false)
.orderByDesc("create_time")
);
}
三、知识库字段重命名
变更内容
将所有 kb_id 改为 knowledge_id,提升语义清晰度。
| 表名 | 变更 |
|---|---|
knowledge.tb_knowledge_base |
主键:kb_id → knowledge_id |
knowledge.tb_knowledge_document |
外键:kb_id → knowledge_id |
knowledge.tb_knowledge_chunk |
外键:kb_id → knowledge_id |
knowledge.tb_knowledge_access_log |
引用:kb_id → knowledge_id |
customer_service.tb_faq |
引用:kb_id → knowledge_id |
影响范围
- ✅ 所有外键约束已更新
- ✅ 所有索引已更新
- ✅ 文档速查表已更新
四、智能体关联
知识库表新增字段
ALTER TABLE knowledge.tb_knowledge_base
ADD COLUMN agent_id VARCHAR(50); -- 关联智能体ID
说明
- 一个知识库可以关联一个智能体
- 智能体可以通过此字段快速查找其知识库
- 智能体表(tb_agent)当前已注释(暂不启用)
五、数据库初始化脚本
initAll.sql(简化版)
-- =============================
-- 城市生命线AI数智化平台 - 数据库初始化脚本
-- 按顺序执行各模块建表SQL
-- =============================
\i createDB.sql
-- 1. 系统基础模块
\i createTablePermission.sql
\i createTableUser.sql
-- 2. 文件管理模块
\i createTableFile.sql
-- 3. 消息通知模块
\i createTableMessage.sql
-- 4. 日志模块
\i createTableLog.sql
-- 5. 配置管理模块
\i createTableConfig.sql
-- 6. 知识库管理模块
\i createTableKnowledge.sql
-- 7. 招投标业务模块
\i createTableBidding.sql
-- 8. 智能客服业务模块
\i createTableCustomerService.sql
-- 9. 智能体模块(暂不启用)
-- \i createTableAgent.sql
使用方式
# 进入PostgreSQL
psql -U postgres
# 执行初始化
\i /path/to/initAll.sql
六、测试/生产环境隔离方案
推荐方案:分别部署
测试环境:
├── 应用服务器:test-server:8080
├── 数据库:urbanlifeline_test
└── 配置:application-test.yml
生产环境:
├── 应用服务器:prod-server:8080
├── 数据库:urbanlifeline_prod
└── 配置:application-prod.yml
配置文件
application-test.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/urbanlifeline_test
username: postgres
password: test123
application-prod.yml
spring:
datasource:
url: jdbc:postgresql://localhost:5432/urbanlifeline_prod
username: postgres
password: prod123
部署命令
# 测试服务器
java -jar urbanlifeline.jar --spring.profiles.active=test
# 生产服务器
java -jar urbanlifeline.jar --spring.profiles.active=prod
优势
✅ 简单清晰:物理隔离,无需代码改动
✅ 安全可靠:测试数据不会污染生产环境
✅ 易于维护:独立部署,互不影响
✅ 性能独立:测试压力不影响生产性能
七、SQL语法修复
修复内容
| 文件 | 问题 | 修复 |
|---|---|---|
createTableLog.sql |
注释语句末尾使用逗号 | 改为分号 |
createTableMessage.sql |
service_type字段缺少逗号 | 添加逗号 |
八、数据库表结构总览
核心表关系
knowledge.tb_knowledge_base (知识库)
├── agent_id → agent.tb_agent (智能体)
└── knowledge_id ← knowledge.tb_knowledge_document (文档)
├── root_doc_id (版本组)
├── version (版本号)
├── is_current (当前版本)
└── knowledge_id ← knowledge.tb_knowledge_chunk (分段)
└── version (乐观锁版本)
隔离字段应用
所有业务表
├── service_type (服务隔离:bidding/customer_service/internal)
└── dept_path (部门隔离:/dept1/subdept1/)
九、最佳实践建议
1. 版本管理
✅ 每次上传新文档时设置 root_doc_id = doc_id
✅ 创建新版本前,标记旧版本 is_current = false
✅ 编辑分段时始终检查 version 字段(乐观锁)
2. 数据隔离
✅ 查询时始终添加 service_type 过滤
✅ 使用 MyBatis 拦截器自动注入隔离条件
✅ 敏感操作添加 dept_path 权限检查
3. 环境管理
✅ 测试/生产分别部署,使用不同数据库
✅ 配置文件使用 Spring Profile 管理
✅ Controller/Service/Mapper 层无需修改
十、待办事项
- 创建数据库迁移脚本(旧表 → 新表)
- 编写单元测试验证版本管理功能
- 配置 MyBatis 拦截器自动注入 service_type
- 准备生产环境部署文档
- 知识库数据导入/导出工具开发
附录:完整字段对照表
tb_knowledge_document 字段清单
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| doc_id | VARCHAR(50) | ✅ | 文档ID(主键) |
| knowledge_id | VARCHAR(50) | ✅ | 知识库ID |
| title | VARCHAR(500) | ✅ | 文档标题 |
| version | INTEGER | ✅ | 版本号(新增) |
| root_doc_id | VARCHAR(50) | - | 根文档ID(新增) |
| is_current | BOOLEAN | ✅ | 是否当前版本(新增) |
| service_type | VARCHAR(50) | - | 服务类型(新增) |
| dept_path | VARCHAR(255) | - | 部门路径 |
| deleted | BOOLEAN | ✅ | 软删除标记 |
tb_knowledge_chunk 字段清单
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| chunk_id | VARCHAR(50) | ✅ | 分段ID(主键) |
| doc_id | VARCHAR(50) | ✅ | 文档ID |
| knowledge_id | VARCHAR(50) | ✅ | 知识库ID |
| content | TEXT | ✅ | 分段内容 |
| version | INTEGER | ✅ | 版本号(乐观锁,新增) |
| embedding | vector(1536) | - | 向量嵌入 |
| deleted | BOOLEAN | ✅ | 软删除标记 |
文档生成时间: 2025-12-02
最后更新: 知识库版本管理、多服务隔离、字段重命名