向量数据库不必单独建一座“烟囱”:谈谈金仓KES的融合数据库架构

一家企业准备上线知识问答系统时,技术团队通常会先列一张采购清单:关系型数据库继续保存业务数据,文档数据库用来放制度和合同,再增加一套向量数据库负责语义检索。如果项目还涉及设备和地图,清单上还要加时序数据库与GIS系统。

这样的方案并非不能用。项目刚开始时,各套系统分工明确,原型也能很快跑起来。真正的麻烦往往出现在上线以后。业务人员刚修改的制度,问答系统还在引用旧版本;已经删除的文档,偶尔还能从检索结果中看到;运维人员排查一次问题,要在数据库、消息队列、同步程序和向量服务之间来回确认。

金仓KES提出的AI时代融合数据库架构,针对的正是这类问题。它把关系、向量、文档、GIS和时序数据放在一套数据库体系中管理。对项目团队来说,这件事的意义并不复杂:原本需要在几套系统之间搬来搬去的数据,可以尽量留在同一个地方处理。

一、系统多了,数据也跟着分了家

(一)一个制度文件,最后可能变成五份数据

以企业制度问答为例。制度发布后,关系型数据库里保存标题、部门、发布时间和有效状态,文档系统保存正文。随后,处理程序读取正文,把内容切成若干片段,调用嵌入模型生成向量,再把片段、向量和少量标签写入向量检索系统。

到这里,同一份制度已经有了几种形态:业务主记录、原始正文、文本切片、向量数据和检索索引。如果前面还有缓存,副本会更多。

开发人员平时看到的是一条完整流程,运维人员看到的却是一串相互依赖的任务。源库写入成功,只能说明制度已经发布,不能说明向量已经生成。向量写入失败时,系统不会自动回到制度发布前的状态,只能依靠重试或补偿程序继续处理。

(二)延迟有时不长,但足以让回答出错

数据同步延迟未必以小时计算。有时只有几分钟,甚至几十秒。不过对于制度更新、风险名单、设备告警这类数据,短暂的时间差也可能让答案失去意义。

例如,业务人员在上午十点把一份制度改为失效。关系型数据库已经完成更新,但切片清理任务在十点零五分才执行。在这五分钟里,大模型仍可能把旧制度当作依据。问题不是模型"不够聪明",而是它拿到的数据已经落后。

(三)删除比新增更容易被忽略

新增数据失败,通常很快就会被发现,因为用户检索不到内容。删除没有同步彻底,反而不容易暴露。源记录已经删除,向量系统中却还保留旧片段,普通查询未必能发现,只有碰巧召回时才会出现。

因此,技术团队需要额外维护对账程序:检查主记录数量、切片数量、向量数量是否一致;发现差异后,再决定单条补偿还是全量重建。系统越多,这类本来与业务无关的工作越多。

二、向量数据离不开业务上下文

(一)相似,不等于可以使用

向量检索擅长从大量内容中找到语义相近的片段,但企业应用不能只按相似度排序。一段文字即使和用户问题非常接近,也可能属于另一个部门、已经过期,或者当前用户没有查看权限。

所以,向量通常要和几类信息一起使用:

  1. 原文编号和片段位置,用于返回出处;
  2. 组织、租户和权限信息,用于限制访问范围;
  3. 状态和有效期,用于排除失效数据;
  4. 模型名称、维度和版本,用于后续重算;
  5. 更新时间和内容版本,用于判断向量是否仍与原文对应。

这些信息大多来自关系数据。如果关系数据和向量分处两套系统,应用只能先从一边召回,再去另一边过滤。这样做不仅多一次查询,还会遇到两个系统数据版本不一致的问题。

(二)金仓KES把多种数据放回同一个业务对象

金仓KES的融合思路不是把所有内容硬塞进一张表,而是让不同类型的数据在同一套数据库中各自采用合适的方式保存。

一台设备可以有设备编号、型号、所属单位等关系数据,也可以有说明书和维修记录等文档数据;故障描述可以生成向量,安装位置可以用GIS数据表示,温度和振动则按时间序列记录。它们形式不同,但都围绕同一台设备。

这样一来,开发人员不必先从关系库取设备编号,再到时序系统查最近指标,随后去GIS系统判断区域,最后把候选编号交给向量系统。数据库可以在更统一的范围内完成关联和过滤,应用只需处理最终结果。

三、从几段代码看实际用法

下面的代码用于说明架构思路。不同金仓KES版本及向量组件的类型、函数和索引写法可能不同,实际项目应以所用版本的正式手册为准。

(一)先把来源关系保存清楚

下面是一张设备知识表的简化示例。除了向量,还保存了组织、状态、原文和内容版本。

sql 复制代码
CREATE TABLE device_knowledge (
    device_id       VARCHAR(64) PRIMARY KEY,
    device_name     VARCHAR(200) NOT NULL,
    org_id          VARCHAR(64) NOT NULL,
    status          VARCHAR(32) NOT NULL,
    area_code       VARCHAR(32),
    location        GEOMETRY,
    attributes      JSON,
    source_text     TEXT,
    content_version VARCHAR(64) NOT NULL,
    embedding       VECTOR(1536),
    updated_at      TIMESTAMP NOT NULL
);

这张表中,source_text用于保存可回看的原文片段,content_version用于确认向量对应哪一版内容。项目中还可以增加处理状态、模型版本和失败原因。这样,运维人员能看出某条数据是尚未处理,还是处理失败,而不必只靠"能否搜到"来判断。

(二)写入时同时记录处理状态

向量一般由应用服务或数据处理组件调用嵌入模型生成。应用写入数据时,可以同时保存向量和版本信息。

sql 复制代码
INSERT INTO device_knowledge (
    device_id, device_name, org_id, status, area_code,
    attributes, source_text, content_version,
    embedding, updated_at
) VALUES (
    :device_id, :device_name, :org_id, :status, :area_code,
    :attributes, :source_text, :content_version,
    :embedding, CURRENT_TIMESTAMP
);

如果向量不能立即生成,项目团队可以把记录状态先设为PENDING。处理成功后改为READY,失败时记为FAILED并保留原因。查询只使用READY数据,重试任务也有了明确范围。

(三)检索时先加业务条件

企业知识检索通常不应直接在全库取相似度最高的前几条。下面的查询先限制组织、状态、区域和时间,再对候选记录进行向量排序。

sql 复制代码
SELECT device_id,
       device_name,
       source_text,
       embedding <=> :query_embedding AS distance
FROM device_knowledge
WHERE org_id = :current_org
  AND status = 'ACTIVE'
  AND area_code IN (:allowed_areas)
  AND updated_at >= :knowledge_start_time
ORDER BY embedding <=> :query_embedding
FETCH FIRST 8 ROWS ONLY;

这里的<=>只是向量距离计算的示意写法。代码真正要表达的是,权限和业务状态应在数据库查询阶段处理,而不是让大模型看完结果后再决定哪些内容能用。

(四)一次查询可以同时用到多种数据

设备运维人员可能会问:"华东区域最近一小时有哪些温度异常的设备,其故障描述又和轴承磨损相似?"这个问题同时涉及关系、GIS、时序和向量数据。

sql 复制代码
SELECT d.device_id,
       d.device_name,
       d.source_text,
       t.temperature,
       d.location
FROM device_knowledge d
JOIN device_metrics t ON t.device_id = d.device_id
WHERE d.status = 'ACTIVE'
  AND ST_Within(d.location, :east_china_region)
  AND t.recorded_at >= CURRENT_TIMESTAMP - INTERVAL '1 hour'
  AND t.temperature > t.temperature_threshold
ORDER BY d.embedding <=> :query_embedding
FETCH FIRST 10 ROWS ONLY;

在多套数据库独立部署的情况下,应用要分别取得几组数据,再在代码中求交集。融合架构下,这些条件可以围绕同一业务对象组织。查询路径短了,排查起来也更直观。

四、RAG落地时,数据库要管住数据边界

(一)大模型只负责组织答案

一个较稳妥的RAG流程是:应用先识别用户身份和问题中的业务条件,数据库完成权限过滤、状态过滤和向量召回,然后把带有出处的片段交给大模型。大模型负责理解问题和组织语言,不负责猜测用户权限,也不负责判断哪一版制度有效。

回答生成后,系统还应记录数据版本、模型版本、召回片段和访问时间。出现争议时,技术人员才能还原当时模型看到了什么,而不是只留下最终的一段文字。

(二)AI直接操作数据库,更需要受控工具

在MCP一类交互方式中,大模型可以调用数据库工具。项目团队更适合把常用能力封装成"查询设备状态""检索制度条款""统计区域指标"等固定工具,而不是直接开放任意SQL。

json 复制代码
{
  "name": "search_device_knowledge",
  "description": "按组织、区域、状态和语义描述检索设备知识",
  "input": {
    "org_id": "string",
    "area_code": "string",
    "query": "string",
    "top_k": "integer <= 20"
  },
  "output": ["device_id", "source_text", "distance", "updated_at"]
}

工具内部仍由数据库执行权限、行数和超时限制。模型只知道工具能做什么、需要哪些参数、会返回哪些字段。这种方式更容易审计,也便于项目人员控制风险。

五、一套数据库主要省下了什么

(一)少搬数据,首先省的是同步工作

融合架构并不是要取消所有ETL。数据仓库、历史归档和跨系统交换仍然需要数据搬运。它减少的是在线AI链路中那些只为适配另一套存储而产生的复制。

当关系记录、原文、向量和其他业务数据可以在同一套数据库体系中管理时,项目团队可以少维护几类连接器和同步任务。数据更新后,不必等待多级传递;数据删除时,也更容易找到关联内容。备份、监控和故障演练的对象随之减少。

(二)运维人员不必在几套系统之间猜问题

多套系统独立部署时,一次检索异常可能来自源数据、消息队列、消费程序、向量服务或应用拼装。每个组件都正常,并不代表整条链路正常。

金仓KES的融合架构不能省掉容量规划、高可用、备份恢复和索引设计,但它能缩短问题链路。很多原来要跨系统检查的情况,可以回到数据库内部查看数据状态、版本和查询过程。对长期运行的生产系统来说,这种简单往往比原型阶段多一个功能更实用。

六、项目落地不必一步铺得太大

(一)先选一个边界清楚的场景

技术团队可以先从制度问答、相似案例检索或设备故障查询中选择一个场景。第一步不是立刻导入全部数据,而是把业务对象理清:主键是什么,原文在哪里,谁有权限,何时失效,更新后哪些向量需要重算。

(二)把更新和删除也纳入验收

很多项目只测试"新数据能不能搜到",却没有测试修改和删除。较完整的验收应包括:更新后多久能检索到新版本,旧片段何时失效,删除能否清理干净,处理失败后能否准确重试。

(三)最后再增加GIS和时序条件

基础知识检索稳定后,项目团队再逐步加入空间范围和实时指标。比如先筛选某一区域的在役设备,再查看最近一小时的告警,最后用向量匹配历史故障。每增加一种数据,都应该对应一个清楚的业务问题,而不是为了展示数据库支持的数据类型。

七、结语

企业建设AI应用时,向量数据库当然重要,但向量从来不是孤立的数据。它对应一段原文、一个业务对象和一套访问规则。把向量单独放在一座新"烟囱"里,早期看起来清晰,后来往往要付出同步、对账和运维的代价。

金仓KES的融合数据库架构把关系、向量、文档、GIS和时序能力放到同一套管理体系中。它所强调的"一套数据库解决所有问题",并不是让所有数据使用同一种结构,而是尽量让相关数据在一个可靠边界内完成关联、过滤和检索。

对项目团队来说,结果很直接:数据少搬一次,副本就少一份;链路少一段,故障点也少一个。AI应用要从演示走向生产,这些看起来并不花哨的改进,往往才是决定系统能否长期运行的部分。

相关推荐
晚安code1 小时前
TransmittableThreadLocal 线程池上下文传递:捕获重放恢复
后端
JoyT1 小时前
Claude Code 多会话协作:会话间消息与并行开发
后端
IT_陈寒1 小时前
SpringBoot自动配置的坑,把我整不会了
前端·人工智能·后端
赵大仁1 小时前
Human-in-the-loop:前端确认流与后端幂等
前端·后端·ai·agent·人机协作
Rain的Java大神之路1 小时前
如何避免订单重复提交
java·redis·后端·面试·架构·rabbitmq·rocketmq
程序员爱钓鱼2 小时前
Rust 泛型 Generics详解:编写可复用且类型安全的代码
后端·面试·rust
小满zs2 小时前
Go语言第九章(错误处理)
后端·go
桦说编程2 小时前
深入理解 FutureTask 状态机——从契约到实现
java·后端·性能优化
程序员爱钓鱼2 小时前
Go 编程实战:指针 Pointer——理解地址、取址与解引用
后端·面试·go