AI Agent正在悄悄推高你的SQL数仓账单

AI Agent 生成语法各异但语义相同的 SQL,击穿数仓缓存,导致成本随交互次数暴增。
文章指出,传统分析栈的成本模型假设少数分析师发出少数固定查询,缓存与物化视图都围绕重复模式优化。但 AI Agent 会为单个用户意图扇出大量语义相似、语法不同的 SQL,导致基于精确文本或哈希的数仓缓存几乎全部失效,计算成本随交互次数而非问题数量增长。语义层解决的是指标口径一致性,无法阻止缓存未命中。修复关键不在数仓内部加缓存,而在数仓之前引入规范化层,将 Agent 查询映射到语义层指标定义或基于意图做去重。领先团队已开始为查询意图埋点、构建以含义为键的缓存,并对 Agent 查询扇出设置硬性上限。
一个被忽略的成本假设
每一套分析栈的成本模型里,都藏着一个隐含假设:少数人类分析师发出少数几种查询,按固定周期重复执行。仪表盘每十五分钟刷新一次,分析师每周一跑同一条队列查询,缓存层、物化视图和数仓自动扩缩容,都是围绕这个模式调优的。这套逻辑运转了二十年,因为生成 SQL 的人耐心有限,问题数量也有限。
AI Agent 没有这个限制,这正是没人标价的问题所在。

没人定价过的使用模式
当 AI Agent 回答"上季度东北地区营收趋势如何"时,它不会只问一次。它会沿着一条链路追问:先确定区域范围,再验证日期区间,然后因为用户的下一句话暗示了不同的粒度,又换一个角度交叉核对。每一次 Agent 会话、每一次重试、每一次自我纠错循环——Agent 不确定第一次查询是否正确,于是换个略有不同的写法再验一遍——都在成倍放大查询量。
这些查询在 SQL 文本层面没有一条是完全相同的。空白字符不同、列顺序不同、Agent 为了清晰自己加了个 CTE、WHERE 子句这次写成 region = 'Northeast' 下次写成 region IN ('Northeast')。对人类分析师来说这是同一个问题,但对数仓查询缓存来说——它通常以精确语句文本或其归一化哈希为键——这是完全不同的查询,每一条都是一次完整的计算作业。
仪表盘为重复而生,Agent 为变化而生
如果只关注正确性,这一点很容易被忽略。仪表盘和语义层这类 BI 工具解决的是信任问题——确保每个人看到的"营收"是同一个数。它们从未被要求解决吞吐量问题,因为吞吐量从来不是瓶颈。一个被五百人查看的仪表盘,仍然只发出一次查询,缓存一次,服务五百次。
Agent 集群把这个比例颠倒了过来。一个用户意图可以扇出成几十条查询,而且这些查询是模型每次现场生成的,不是从固定库里检索的。语义层仍然可以保证"营收"在各处代表同一个聚合口径——这个问题真实且值得解决——但当一个查询的措辞变化时,它无法阻止数仓重新执行一次完整的扫描聚合。你可以有完美治理的指标定义,却眼看着计算账单翻三倍,因为治理从来不是这里的成本杠杆。量和缓存未命中率才是。
缓存为什么会失效:语义相似 vs 语法相同
查询缓存、结果缓存和物化视图都建立在一个前提上:"同一个问题"产生"同样的字节"。当查询由少数人通过少数 BI 工具用固定模板编写时,这个前提成立。一旦由 LLM 来写 SQL,它就崩塌了,因为 LLM 没有动力收敛到规范形式。它会根据温度参数、提示措辞或前一个工具调用的不同,把语义等价的查询写成十几种不同的语法形状。
这和 text-to-SQL 的准确率问题是完全不同的失败模式。查询可以完全正确,却依然是一次缓存未命中。你可以有调优良好的 Agent、干净的语义层、快速的模型,数仓的表现却依然像每一条查询都是全新的——因为在语法上,它确实是。结果就是一条随 Agent 交互次数增长的成本曲线,而不是随不同问题数量增长——这两个数字相差一个数量级甚至更多。
查询缓存与结果缓存的键机制
数仓查询缓存通常以查询语句的精确文本或其归一化哈希作为键。归一化一般只做轻量处理:去除多余空白、统一大小写、折叠字面量格式,但不会做语义层面的重写。这意味着 WHERE region = 'Northeast' 与 WHERE region IN ('Northeast') 即便逻辑等价,也会产生不同的哈希,各自触发一次完整执行。结果缓存则进一步要求命中同一键且结果仍在有效期内。物化视图虽能预先聚合常见过滤条件,但其匹配同样依赖查询能否被重写器识别为等价形式。当查询由 LLM 现场生成时,这些机制的前提——存在稳定、收敛的查询模板——不再成立,缓存命中率会随语法多样性上升而急剧下降。
LLM 的温度参数与采样多样性
温度参数控制 LLM 生成时对概率分布的采样方式。温度越高,输出越随机多样;温度越低,越倾向于选择高概率 token。但即使温度设为 0,由于提示措辞、上下文长度、前序工具调用结果不同,同一意图仍可能生成不同 SQL 结构。LLM 的训练目标是最小化下一个 token 的预测误差,而非收敛到某一种规范 SQL 写法,因此它没有内在动力把 region = 'Northeast' 和 region IN ('Northeast') 统一。这种语法层面的发散是缓存失效的根本原因,与查询正确性无关。
基于嵌入的查询去重
嵌入是把文本映射为高维向量的表示方法,语义相近的文本在向量空间中距离更近。基于嵌入的查询去重,是在查询执行前将 SQL 或其解析出的意图编码为向量,检索近期是否有语义等价的请求。若底层参数在可接受的新鲜度窗口内匹配,则直接返回缓存结果,而非重新扫描数仓。它解决的是“语义相同但语法不同”的命中问题,与精确文本缓存互补。工程上需要处理相似度阈值、参数提取、新鲜度窗口和误命中风险,因此更接近一个路由层而非简单缓存。
修复方案:在数仓之前做规范化
直觉反应是在数据库层投入更多缓存——更好的执行计划缓存、结果集记忆化、针对常见过滤条件调优的物化视图。它们有帮助,但很有限,因为它们打错了层次。数仓只能缓存它能识别为相同的东西。修复必须发生在查询到达数仓之前:一个规范化层,把 Agent 生成的 SQL——或者更好,把它的底层意图——在执行前映射到归一化表示。
具体做法是拦截 Agent 生成的查询,把它们重写到语义层的指标定义上,而不是让它们直接命中原始表——这次不是为了治理,而是因为像 revenue(region=Northeast, period=last_quarter) 这样的指标调用,天生就比五条措辞各异的原始 SQL 语句更容易缓存。这也包括应用层的基于嵌入的查询去重:在查询执行前,用解析出的意图而非文本,检查近期是否运行过语义等价的请求,若底层参数在可接受的新鲜度窗口内匹配,就直接返回缓存结果。
这是一个与出于正确性目的构建语义层截然不同的工程问题。它是一个位于 Agent 和数仓之间的路由与缓存问题,几乎还没有哪套分析栈具备它,因为在 Agent 开始产生人类团队永远达不到的查询量之前,几乎没人需要它。
分析工程师现在真正该建什么
抢先解决这个问题的团队,不是在买更大的数仓。他们在 SQL 生成之前就对查询意图进行埋点——记录 Agent 实际想查什么,而不只是它发出的那条语句——再用这份意图日志构建一个以含义而非文本为键的缓存。他们也在给 Agent 的查询扇出设置硬性上限,就像 API 网关限制重试一样,因为一个每次回答都自我纠错三次的 Agent,是在为一种边际准确率提升付出三倍计算成本,而那点提升往往不划算。
这些都不是什么奇特的基建。它更像面向分析查询的 CDN,而不是某种新的数据库特性。但它要求分析工程师把 Agent 当作一种流量模式来看待,而不只是语义层的一个新消费者。语义层回答"营收是什么意思",规范化层回答"十分钟前我们是不是已经用别的措辞回答过这个问题了"。目前几乎每一套 AI+BI 栈都有前者,却完全缺失后者,而数仓账单正悄悄从这道缺口里流走。
相关推荐

“黑色十月”:AI挖出史上3%严重漏洞?
Reddit 热帖称过去一个月发现了史上 3% 的严重软件漏洞,被称为「黑色十月」。本文拆解这一说法的统计口径问题,分析 AI 辅助代码审计如何加速漏洞发现,以及开发者和企业该如何应对补丁窗口缩短的挑战。

微软Project Gecko:用AI为非洲农民架起语言桥梁
微软Project Gecko项目推出PharmaChat应用,让非洲农民用母语提问,通过AI返回精准视频片段和农耕书籍章节。项目还发布三个交互式手册,推动包容性AI发展。

Node.js语音笔记App:语音转文字API选型指南
为Node.js语音笔记应用选择语音转文字API?对比AssemblyAI、Deepgram、Google Cloud和Whisper的免费额度、定价与Node集成体验,给出分阶段选型建议。