金仓KES向量数据库实战:一条SQL干掉ETL,机器人不再把停产货当现货卖
一、背景:一套跑了一年的"三件套"
1.1 先说项目
我在一家制造企业做平台开发。去年接了个活儿,给内部客服和售后搭智能问答,说穿了就是 RAG。把几十年的产品手册、维修案例、工单记录喂给大模型,一线员工提问的时候,系统把最相关的资料片段捞出来递给模型,模型再组织成人话回答。
去年上的线。用的人不少,日均几千次提问吧。
别看我现在说得轻巧,当年的架构可是照着行业标配抄的"三件套"。MySQL 存业务元数据和文档目录,一个专用向量数据库存 embedding,中间靠 ETL 任务搬砖。就这套东西,跑了一年。
1.2 当时是怎么切的
分工大概这样。文档正文和切片进 MySQL,运营同事要审核管理嘛。切片算出来的 embedding 灌进向量库,建 ANN 索引,管相似度检索。至于权限、产品线、有效性这些业务属性,两边都存了一份,向量库里放元数据字段用来过滤,MySQL 里那份当权威版本。
算法组的小林当时就嘀咕过,说两边都存,早晚要出事。我还挺不耐烦,回他说 ETL 十分钟跑一次呢,能出啥事。
嗯。这个 Flag 立得相当标准。
二、出事了:机器人把停产货当现货卖
2.1 周二下午
售后群炸了。机器人信誓旦旦地告诉客户,某款停产大半年的控制器"目前有货,可以下单"。客服没多想,照着回了。客户还真去下了单。
我到现在都记得排查的过程。顺着问题向量去检索,命中的确实是那款产品的资料,相似度还挺高,检索这步没毛病。回头查元数据,MySQL 里这条产品三个月前就标记停售了。卡在哪儿?ETL。某次向量库升级之后,同步任务的鉴权配置失效了。注意啊,任务没报错,它就是安静地不干活了。停售标记从头到尾没走到向量库的过滤字段里。
更头皮发麻的是,这种安静失败不是头一回。上一次是权限字段,某部门的文档下线了,向量库里的副本还活得好好的,测试同学闲逛才发现的。两次一个根儿。同一份业务事实存两个系统,靠异步任务保持一致,那延迟和漂移就不是会不会发生的问题了,只是什么时候被人撞见的问题。
2.2 复盘会上算的账
复盘会开完我没走,一个人把这一年的账摊开来算了算。
同步链路,四道工序,解析、切片、向量化、搬运,哪道都可能卡住,监控只盖得住两道。混合查询也别扭,用户的真实问题从来不是纯相似度,是"某产品线、我有权限、还没过期的资料里搜"这么一串。向量库的元数据过滤又弱,只能应用层先查 MySQL 拿 id,再攥着 id 列表去向量库搜。权限范围一大,列表好几千个,性能当场趴窝。
运维是双份的苦。两套库两套备份两套告警。老徐半夜被告警吵醒,原话是,我还得先想半分钟这次是谁家的。
那天下班路上我一直在想小林那句话。
三、换思路:让向量长回数据库里
3.1 一个朴素得要命的问题
后来某次内部讨论,小林又开口了。向量不就是表里的一列吗,凭什么不能跟别的字段住一张表、进同一个事务?
会议室安静了几秒。这问题听着简单,把我们整个架构的前提给问松了。
顺着这个方向查资料,最后落在金仓数据库 KES 的向量能力上。思路跟小林那个问题一模一样,向量作为一种数据类型直接建在关系表里,跟数值、文本、JSON、GIS、时序一块儿活在同一个库里。没有搬运这回事,一条 SQL 里向量检索和普通条件一起下。
坦白讲我起先犯嘀咕。专用向量库那边迭代得跟飞一样,数据库内置的向量能力会不会是个玩具?亲手测了两件事才踏实。一是人家自研实现了 HNSW 和 IVFFlat 两种近似索引,还带 SIMD 指令级的加速,不是扫个表糊弄事。二是向量数据直接吃数据库的 ACID 事务,这个市面上不少 NoSQL 形态的向量库给不了,而对我们这种元数据改了向量必须跟着变的场景,恰恰是要命的那条。
3.2 新架构长什么样
改造完我盯着看了半天,有点不习惯,就这么简单?
原来元数据和向量分两个库、ETL 搬着砖、滞后还漂移,现在一张表,向量就是其中一列,改完即生效。原来相似度和过滤分两步走、应用层拿针线缝合,现在一条 SQL 混合检索全下推。原来备份监控权限配置什么都得来两份,现在一份。老徐的原话是,晚上能睡整觉了。
四、动手改造
4.1 建表
文档切片表直接带上向量列。我们的 embedding 模型输出 768 维,类型声明里就写 768,别的不用多想:
CREATE TABLE doc_chunks (
id BIGSERIAL PRIMARY KEY,
doc_id BIGINT NOT NULL,
doc_title TEXT,
chunk_text TEXT NOT NULL,
embedding VECTOR(768) NOT NULL,
product_line TEXT,
is_active BOOLEAN DEFAULT TRUE,
dept_perm TEXT[],
updated_at TIMESTAMPTZ DEFAULT now()
);
多看一眼 is_active 和 dept_perm 这俩字段。停产标记、部门权限,原来住在另一个库里,现在跟向量睡同一行。产品停售了?一条 UPDATE 把 is_active 置掉,事务提交那一瞬间,检索结果里就再也见不着它了。开头那个事故,搁这个架构下压根没有发生的土壤。
4.2 索引选型,加两个血泪坑
两种索引我们都实测了,代码一起贴给你:
-- HNSW:多层图结构,召回高、查询快,就是吃内存、建得慢
CREATE INDEX idx_chunk_hnsw ON doc_chunks
USING hnsw (embedding vector_cosine_ops);
-- IVFFlat:先聚类再倒排,省内存、建得快,拿 probes 调精度
CREATE INDEX idx_chunk_ivf ON doc_chunks
USING ivfflat (embedding vector_cosine_ops);
最后定的 HNSW。语料百万级,内存扛得住,而客服场景对召回率敏感,漏一条关键维修案例可比慢十毫秒严重多了。你要是向量上亿、内存又紧,那 IVFFlat 值得先试。补一句,这儿的索引在数据插入更新时是实时维护的,不存在建完索引就不让改数据那种憋屈事。
坑,踩了俩。
第一个,IVFFlat 千万别在空表上建。它先对全量数据聚类再分桶,空表建出来的分桶全是错的,召回惨到没法看。我们当时还以为是版本 bug,排了一晚上,最后发现是自己用法不对。先灌数,后建索引,顺序别反。
第二个更隐蔽。用余弦距离的话,向量入库前要归一化,不然模长会掺进距离里捣乱,排序结果莫名其妙地不对。我们有一阵子检索质量忽好忽坏,查了好几天才定位到这儿,说起来都是泪。
4.3 检索就一条 SQL
改造后最爽的部分。用户提问的完整检索,就这一条:
-- q_vec 是应用侧把用户问题向量化后传进来的参数
SELECT doc_title, chunk_text,
embedding <=> q_vec AS distance
FROM doc_chunks
WHERE is_active = TRUE
AND product_line = '工业控制器'
AND dept_perm @> ARRAY['after_sales']
ORDER BY embedding <=> q_vec
LIMIT 5;
看看 WHERE 里混了些什么。有效性,产品线,数组权限判断,再搭上 <=> 算的余弦距离排序。原来那个先查 id 列表再传给向量库的两段式,整个被压进数据库一次执行。权限列表几千条也不虚了,过滤条件下推,扫描范围先砍一大截。
我观察下来,这是融合架构最被低估的地方。大家盯着向量检索性能比来比去,很少有人算省掉的那条同步链路值多少钱。
4.4 意外收获
顺手的惊喜,值得一小节。向量类型支持加减、数乘、拼接,还带 AVG、SUM 这类聚合。我拿它算过全部语料向量的均值,专门捞离群的切片:
-- 找跟语料中心离得最远的切片,多半是切坏了的或者内容异常的
WITH center AS (
SELECT AVG(embedding) AS c FROM doc_chunks
)
SELECT id, doc_title, embedding <=> c AS distance
FROM doc_chunks, center
ORDER BY distance DESC
LIMIT 20;
跑出来一瞧,果然一堆切稀碎的表格和乱码 PDF。以前这种活儿得导出去写 Python 脚本,现在 SQL 一条。
五、跑了三个月的账
说几个拿得出手的数。检索链路里彻底没有 ETL 这号角色了,数据新鲜度从最多滞后十分钟变成事务级。混合检索的 P95 从 180ms 掉到 40ms 上下,大头是省了两段式那个应用层往返。运维对象两套变一套,老徐的告警群肉眼可见地清净了。至于停产产品当现货卖这类事故,架构上没有它发生的土壤了。
代价也得老实交代。单一库资源共享,高峰期向量检索和普通业务查询会抢 CPU。我们靠资源隔离配置压了压,不算完美,但跟伺候同步链路比,省心太多。
六、写在最后
这回改造给我最大的触动是,AI 应用的架构难题好多时候不在模型身上,在数据怎么组织。向量数据库这个词听着像要开新世界,扒开看,向量就是一种数据形态嘛,它在关系库里完全能活得好好的,还顺手把事务、权限、混合查询这些老手艺全带过来了。
一套数据库解决所有问题,这话说得太满我不学。但对中等规模的 AI 应用,我的建议就一句,先别急着上第三套存储,看看手头的库能不能把向量装下,多半能省出一条同步链路,外加好几个不眠之夜。
下一步打算把工单的时序数据也并进来,让检索结果带上"这故障最近是不是高发"的判断。库就在那儿,一张表的事儿。老徐说了,这回他等着看。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)