资讯动态

从低代码到AI交互:多表查询引擎的演进之路

发布时间:2026/9/16 21:38:50 来源:尧图企业网站定制
做了几年查询配置类产品我有个越来越强的感受低代码/无代码这套东西解决“表单录入、简单报表”这类问题很顺手但一旦进入多表查询这种需要复杂关联、语义理解和动态编排的场景拖拽配置器的优势就会迅速变成负担。正好我们团队这两年把一个多表查询引擎从低代码/无代码架构整体演进到了AI交互驱动的新版本整个过程踩了不少坑也把两代方案各自的边界摸得比较清楚。这篇文章会把两代引擎的核心设计、实操细节和迁移过程完整写出来适合正在做低代码平台、查询分析工具或者准备把AI能力接入内部系统的朋友参考。1. 低代码/无代码时代的引擎第一代设计是怎么长出来的1.1 最初的业务诉求逼我们走上了“配置化”路线当时要解决的业务问题其实很常见公司内部有订单、客户、产品、库存、物流好几套业务表运营、财务、客服每天都要做各种跨表查询比如“这个月华北区哪些客户的订单金额超过了10万并且有未发货明细”。在最早的原型阶段我们直接让业务同学写SQL结果就是线上出现了大量“SELECT * FROM 订单 LEFT JOIN 客户 ON ...”风格的慢查询甚至有人把几个大表做了笛卡尔连接直接把数据库压到告警。所以第一代引擎的目标很明确把查询能力封装成“配置化”的让非技术人员通过拖拽表单就能拼出多表查询。当时的想法是把表关系、字段语义、常用筛选条件这些沉淀成元数据前端做成可视化配置界面后端根据配置自动生成SQL并执行这样既保证查询正确性又避免用户直接操作数据库。这正是低代码/无代码平台最常见的“元数据驱动 可视化配置”模式。1.2 第一代架构的核心元数据驱动 查询树编排第一代引擎可以拆成三块元数据层、配置交互层、查询执行层。元数据层负责描述“有哪些表、表之间怎么关联、哪些字段能查、哪些字段需要脱敏”。我们没有用特别重的数据字典工具而是用了一套JSON Schema每个表对应一个实体定义字段类型、是否可筛选、是否可展示、关联关系全部写在里面上线时加载到内存后续改配置基本不用发版。配置交互层是典型的低代码前端左侧是字段列表中间是画布右侧是筛选条件区。用户点选字段再从关联关系下拉里选择“订单属于哪个客户”前端会把所有操作组装成一棵“查询树”。这棵查询树不是SQL而是一种中间结构节点类型包括“表节点”“关联节点”“筛选节点”“聚合节点”“排序节点”后端拿到查询树之后再做翻译。这块最值得说的其实是关联关系的设计。多表查询最容易出错的点就是JOIN写错所以我们把关联关系全部预定义好用户不需要理解“LEFT JOIN”和“INNER JOIN”的区别只需要回答业务问题“订单如果没有客户信息还要不要显示”。这个选择在翻译层直接映射成不同的JOIN类型避免了一大批低级错误。1.3 查询树到SQL的翻译看着简单细节全是坑查询树翻译成SQL的流程我拆过很多遍核心步骤是这样的从查询树里提取所有需要查询的实体确定表列表。根据实体间的关联节点生成FROM子句和JOIN条件。把筛选节点里的业务条件如“订单金额大于10000”翻译成SQL条件表达式。如果存在聚合节点按聚合字段分组并处理HAVING条件。最后加上权限过滤条件比如“只能看自己负责的客户”这部分由后端强制拼接。当时我们用的是一套自研的Java翻译器没有直接用ANTLR那一套因为查询树的表达能力有限可控性更好。真正的坑出现在“多级关联”上订单关联客户客户关联销售区域区域关联大区用户想查“大区负责人是张伟的所有订单”。业务上这只是一个四层JOIN但在UI上就是四层下拉选择而且每个关联方向都要解释清楚是“从订单找大区”还是“从大区找订单”。很多低代码平台在这里就开始失控了配置出来的查询跑出来结果明显不对但用户自己看不出来。1.4 第一代引擎的真实体验能用但远远不够“智能”第一代上线以后确实把“普通业务同学自己查数”这个需求接住了起码SQL注入和乱写JOIN的问题解决了数据库也稳了很多。但我们慢慢发现了三个致命问题。第一个是配置成本高。一个稍微复杂一点的查询比如“统计过去30天每个品类的退货率并和上月对比”用户在界面上要点二十多下还要理解“关联类型”“聚合口径”这些概念实际上并没有比学SQL简单多少。第二个是“可解释性差”。用户拖出来一个查询得出一个数但没人能讲清楚这个数的口径是否准确。很多业务争议最后都落到“你查的到底跟我查的是不是同一个东西”配置过程越复杂这种争议越难解决。第三个是“改动脆弱”。业务需求变了比如要加一个筛选条件用户就得回到配置界面重新拖一遍相当于把查询重做了一次。低代码在这里的问题就是“可配置的尽头是复杂度复杂度的尽头是重新开发”。这也让我开始认真思考一个方向既然自然语言才是人最习惯的表达方式为什么不让用户直接问问题而是先学会拖拽配置器这个念头直接催生了第二代引擎。2. 为什么说低代码在这里摸到了天花板多表查询的本质问题2.1 多表查询真正的难点不是“拖拽次数”而是“语义理解”低代码/无代码平台把大量精力花在了“降低操作门槛”上比如拖拽、下拉、回填、校验界面越来越漂亮但多表查询的困难从来不在“操作”层面。真正难的是三块第一业务口径不统一“销售额”到底是含税还是不含税、退货算不算、定金算不算不同场景完全不同第二表关系隐藏在业务语义里光看字段名你是不知道“客户ID”和“往来单位ID”其实是同一件事第三查询本身是一个动态推导过程从问题到SQL中间隔着好几层逻辑判断。这些问题配置化界面解决不了因为你只是在给用户一个“填空模板”模板再复杂也覆盖不了所有业务问法。这就像给用户一本厚厚的填表说明而不是让他直接说出来想要什么这不是真正的降门槛只是把门槛从“写代码”换成了“理解抽象规则”。2.2 低代码方案的架构性代价配置逻辑与服务端深度耦合第一代引擎做深了以后架构上会出现一个很难受的局面查询翻译器的复杂度跟着配置项的增多不断膨胀。今天加一个“时间智能筛选”明天加一个“同环比计算”后天加一个“多级审批状态过滤”每一个配置项都要在查询树结构、UI组件、翻译器、权限校验链路里同步修改。有一次我们只是想加一个“按最近N个自然周统计”的配置结果牵扯到元数据模型调整、前端新增日期选择组件、翻译器增加新的时间窗口函数映射、还要处理时区问题前后排了差不多两周才稳定上线。在低代码体系里业务灵活性通常是以“配置项的复杂度”为代价换来的配置项越多系统本身就越像一个需要专业开发的“内部框架”离低代码的初衷反而越来越远。另外第一代配置器在处理“模糊需求”时会很痛苦。用户只知道自己要“看一下最近销售不太好的区域”但“不太好”怎么定义低于平均低于上月连续三周下滑低代码配置器会强迫他把这个定义抽象成若干下拉条件而用户往往自己都还没想清楚口径就被界面绑架了。这也是我们把第二代引擎的重心彻底转向AI交互的原因。2.3 AI交互天然适合多表查询是因为它把“语义”放在了“操作”前面我后来想通了一个道理AI交互之所以适合多表查询不是因为它能“自动写SQL”而是因为它强制系统先做“语义理解”再走查询链路。用户说“看一下最近销售不太好的区域”系统必须先解析出查询对象是“区域”衡量指标是“销售额”时间范围是“最近一段时间”“不太好”的定义需要动态判断比如“低于系统平均销售水平”或“环比下降超过10%”。这个理解过程恰好对应了多表查询当中最难的“口径构建”环节。配置器让你从操作层面逐项构建口径AI则从意图层面直接接收口径系统的核心工作从“翻译用户操作”变成了“翻译用户意图”。这也是第二代引擎的架构主线。3. 第二代引擎AI 交互驱动的多表查询引擎设计全过程3.1 第二代整体架构意图解析 语义层 查询生成 校验执行第二代引擎的架构跟第一代有一个很根本的区别第一代的过程是“用户操作配置器 - 操作转查询树 - 查询树转SQL”第二代则是“用户自然语言 - 意图与语义理解 - 查询计划 - SQL生成 - 校验与执行”。这个转变其实不是把第一代拆了重写而是在第一代执行层的基础上增加了一个“AI交互前端层”和一个“语义理解服务层”把原来由人工拖拽完成的工作交给了模型加规则引擎。整体拆成四块自然语言交互层负责收集用户问题支持追问澄清比如“你说的销售区域是省还是城市级别”。语义理解服务利用大模型把用户问题解析成“查询意图”再结合业务元数据生成“逻辑查询计划”。查询生成与校验把逻辑查询计划转换成可执行的SQL并做正确性、权限、资源消耗的校验。执行与反馈层沿用第一代引擎的查询执行器加入结果解释功能让用户能看到“这个结果是怎么算出来的”。这个架构最关键的一点是我们并没有让大模型直接“自由发挥”写SQL而是把大模型当成一个从自然语言到结构化查询计划的“翻译官”。这样做的原因后面会详细讲。3.2 语义层设计凭什么 AI 能懂“客户ID”和“往来单位ID”是同一个东西多表查询引擎最核心的资产其实不是模型而是“语义层”。语义层等于把第一代那套元数据信息升级成了“机器可读的业务知识库”里面包含三类内容实体与字段的物理定义表名、字段名、类型、注释。实体间的关联关系外键关系、方向、一对多还是多对多。业务口径规则“销售额订单金额-退款金额”、“有效订单状态为已支付”、“区域层级省-市-区”。第二代的AI能力在上层做理解底层依赖的业务知识全部来自语义层。用户问“每个省的有效销售额”系统先从语义层里查“销售区域”这个词发现它可能对应“客户表.省份”和“区域维度表.省份名称”再根据关联关系决定用哪条路径来做关联。如果没有这层约束大模型很容易把“省份”理解成订单表里的一个文本字段直接按字符串分组结果就错了。这套语义层的建设必须靠业务团队和数据团队反复梳理不太可能一步到位。我们一开始只是把第一代元数据导进来跑了一周就发现了大量口径对不上的情况比如“金额”在不同表里分别代表含税、不含税、已支付、毛利全部堆在一起AI再聪明也分不清。后来我们给字段加了“业务场景标签”并且在语义层里写清楚每个标签对应的计算规则情况才好转。3.3 从自然语言到查询计划不直接生成SQL先生成中间表达式很多团队做“Text-to-SQL”喜欢让大模型直接输出SQL实测下来的结论是小规模表结构还行表一多、关联一复杂直接生成SQL的准确率会掉得很快而且完全没法做权限控制。第二代的处理方式是让大模型先生成一个“查询计划”这个计划是一种领域特定语言DSL有点像第一代的查询树但表达能力更强。一个典型的查询计划长这样{ query_type: aggregation, measures: [ {field: order.amount, aggregation: sum, alias: total_amount} ], dimensions: [ {field: customer.region, granularity: province} ], joins: [ {from: order, to: customer, type: inner, on: order.customer_id customer.id} ], filters: [ {field: order.status, operator: in, value: [paid, shipped]}, {field: order.created_at, operator: between, value: {type: relative, unit: month, amount: -1}} ], having: [ {field: total_amount, operator: , value: 100000} ] }大模型只负责把自然语言解析成JSON不做SQL拼接。之后再由一个“计划执行器”把JSON翻译成真正的SQL。这套设计的好处有三个有约束的JSON比自由文本SQL更容易做校验JSON里的字段名、操作符都是枚举值模型不容易乱生成。字段、关联关系的判断可以跟语义层深度绑定模型从预定义的候选列表里选而不是凭空创造。权限过滤可以在执行器这一层强制拼接不管AI怎么理解最终执行的SQL都必须带上“当前用户只能看哪些数据”的条件。3.4 查询生成与自校验AI 会一本正经地胡说八道必须加上这道保险AI生成查询计划最大的坑是“幻觉”典型的情况有三种第一种是生成了不存在的字段名比如把“客户级别”写成了“customer.level”但语义层里只有“customer.LevelCode”第二种是JOIN方向错误比如用户问“没有订单的客户”正常应该用LEFT JOIN从客户表出发看订单但模型可能直接按订单表出发把没下过单的客户丢了第三种是筛选条件口径理解错误比如“最近一个月”到底是指自然月还是滚动30天。我们的应对方案是做一套“生成后校验”管线在查询计划进入SQL翻译之前先跑四个检查步骤字段存在性检查查询计划里所有字段必须在语义层注册过不存在的直接报错并提示AI重新生成。关联路径检查检查JOIN路径是否合法是否存在环是否满足预定义的关系方向。口径规则检查确认查询计划里的筛选字段是否命中了业务口径配置如果命中但口径有冲突比如用户要按“销售额”排序但“销售额”在不同区域定义不同则触发澄清流程。安全与资源检查估算查询涉及的表大小和JOIN复杂度超过阈值就拒绝执行或提示用户缩小范围。这四步合在一起相当于给AI生成结果加了个“语法检查器加业务检查器”。实测下来经过自校验后查询计划的可用率从最初的63%提升到了接近87%后面再通过追问澄清能到92%左右。这个数字已经足够支撑业务同学日常使用了。3.5 从传统低代码迁移过来的三条实操路径如果你现在手上也有一套低代码查询引擎想演进到AI交互模式我建议不要直接推倒重来。我们当时的迁移策略分三步走每一步都保持了线上系统的可用性。第一步是“并行模式”把AI交互作为老引擎前面的一个可选入口用户既可以用原来的拖拽配置器也可以直接输入自然语言AI把结果转成查询计划以后再落到老执行引擎上跑。这一步基本不动老系统只是接入了一个“AI前端”。第二步是“语义层补全”集中精力把老引擎的元数据升级为语义层。老引擎的表关系、字段定义已经有了缺的是业务口径和场景标签这一步最费时间但决定了AI交互的上限。第三步才是“执行层优化”等AI交互的调用量上来了再回头优化查询执行器比如引入更智能的JOIN顺序优化、物化视图加速、查询结果缓存等。我们用了差不多一个季度完成了三步迁移业务部门完全无感只是发现查询入口变了。4. 两代引擎的对比与核心收益低代码做不了的事AI 交互做成了4.1 两代引擎能力对照我整理了一张两代引擎的能力对照表方便有类似项目的人直接参考维度第一代低代码/无代码引擎第二代AI交互引擎用户表达门槛需要理解字段、关联、聚合等概念用自然语言直接描述需求复杂查询支持多级关联配置繁琐容易出错语义层自动匹配关联路径口径一致性依赖用户自己选择正确字段语义层内置业务口径自动命中新需求响应速度需要新增配置项并改动多个模块语义层补一条规则即可可解释性查询树展示业务人员基本不看生成结果附带“查询解析过程”说明权限控制后端强制拼接比较稳妥查询计划校验后统一执行可控性更高性能风险用户配置可能导致复杂JOIN自校验阶段提前做资源评估从表里能明显看到两代的差异不是“UI好不好看”而是“系统是不是承担了语义理解的责任”。低代码把理解责任全部交给了用户AI交互把理解责任接管到了系统这一侧这是本质区别。4.2 业务侧的真实反馈他们是这么用新引擎的第二代上线之后我们收集了一些典型的业务使用场景能很好地说明AI交互的价值。运营同学问“帮我看看华东区哪些品类的毛利率连续两个月低于10%”系统先识别出“毛利率”这个指标发现它不在物理表里而是一个由“销售收入”和“销售成本”计算出来的口径指标于是自动生成子查询再按品类和月份分组做对比。这个查询如果放到第一代用户需要知道毛利率底层依赖哪两张表还要自己配置子查询和窗口函数基本就不可能完成。财务同学的问题是“上季度各渠道的回款金额和去年同期对比”这里面有多个隐藏逻辑渠道维度在回款表和订单表里有两套取值需要渠道映射表做关联去年同期需要把时间条件做动态计算而不是简单写死日期。这些规则如果都让用户在低代码界面上手动选几乎等于让业务人员自学数据仓库建模。还有客服同学直接用新引擎查“某个客户最近半年的工单和退款记录按时间排列”这种跨实体关联查询在第一代要拖五次以上才能出来现在一句自然语言加上结果解释基本半分钟搞定。业务侧的整体评价是“终于不用研究查询条件怎么配了只需要会说话就行”。4.3 一个很重要但容易被忽略的点AI 交互下的权限模型迁移到AI交互之后权限问题不是变简单了而是变复杂了。原因是用户在低代码配置器里权限边界是“显性”的系统只展示他有权访问的字段但在AI对话里用户可能问一个范围很大的问题比如“全公司每个部门的工资总额”虽然生成出了查询计划但用户实际没有权限看所有部门的数据这时候如果直接执行就出问题了。我们的解法是把权限过滤做成了“两道闸门”。第一道闸门在语义理解阶段系统在生成查询计划时只会从用户已有的数据权限范围里选择字段和维度用户无权访问的字段根本不会进入候选列表。第二道闸门在执行阶段SQL翻译器会强制拼接行级权限条件比如在部门表上加“dept_id IN (用户可访问部门列表)”不管AI生成了什么最终SQL都必须经过这一层。两道闸门缺一不可第一道避免“AI把用户没权限的数据生成出来造成幻觉”第二道防住任何绕过检查的漏洞。5. 实际落地中踩过的坑这些问题可能你也会遇到5.1 大模型“一本正经胡说八道”怎么通过追问澄清来兜底AI交互引擎上线初期最大的翻车现场是模型把业务词理解错了。比如有用户问“看看最近30天流失的客户有哪些”系统把“流失”直接翻译成了“status lost”但业务上“流失”是指“超过90天没有下单且没有售后记录”的客户是一个需要跨订单表、售后表联合判断的规则不是字段值。后来我们把容易混淆的业务术语增加了“歧义处理机制”。当AI生成的查询计划命中了一个存在多语义的字段或规则时系统不会直接执行而是先向用户确认“你提到的‘流失客户’是指90天未下单且无售后记录还是状态标记为流失”实测确认这步能把查询准确率提升一大截但也引入了额外交互成本。最终我们采用了一个折中策略对高置信度的查询直接执行对低于置信度阈值的查询才触发追问。这样既保证准确率又不至于每次都要用户多一步操作。5.2 生成结果对了但性能爆炸了多表 JOIN 的另一个难关刚开始我们把AI生成查询的准确率调上去之后很快就遇到了性能问题。典型场景是用户问“所有客户的历史累计消费排名”AI语义层自动关联了订单表、退款表、优惠券抵扣表生成出来一个四表大JOIN加全量分组聚合结果跑了40多秒还没出来直接把生产库的连接池打满。我们后来在自校验阶段加入了一个“执行计划预估算”模块根据表行数、关联基数、筛选条件的选择率粗估SQL执行的行数和耗时超预算就直接拦住并提示用户添加更严格的筛选条件或者选择预聚合报表。同时我们给高频查询配置了结果缓存同样的查询命中缓存直接返回省掉大量重复计算。这个坑在第一代是做配置器时完全不用考虑的因为操作复杂度天然限制了查询规模而自然语言表达太容易“漫天要价”了。5.3 别让 AI 直接写 SQL一个差点失控的试验过程中我们也做过一个对比试验让人工智能模型绕过查询计划直接从语义层生成最终SQL不做中间检查。结论是“小表场景下表现惊艳大表场景下风险极高”。模型在8张表的范围内表现还能接受到了十几张表、上百个字段的复杂业务库生成的SQL经常出现重复JOIN同一张表、漏掉过滤条件、用错聚合函数等问题而且因为SQL是自由生成的无法用枚举校验排查起来特别痛苦。那之后我们定了条规矩AI必须生成结构化查询计划执行器只认查询计划不认SQL。如果业务团队希望直接用自然语言生成SQL跑数我建议要么限制在“单表查询”这种低风险场景要么必须加上极其严格的执行前检查和人工确认流程不然很容易变成线上事故。5.4 语义层的建设这是一场持久战别指望一步到位最后说一下最大的隐形工作量——语义层建设。很多人听到“AI多表查询”以为核心就是调大模型接口实际上大模型能占到的工作量可能只有两成剩下的八成都在语义层的数据梳理、口径对齐、关系校验这些脏活累活上。我们在第一期只覆盖了核心业务域的四张表和二十多个口径标准产品跑起来以后新需求还是会不断冒出新的口径比如“新客的定义到底是首单时间在30天内还是注册时间在30天内”。这些不可能靠AI自己悟出来必须由业务和数据团队同步确认。建议想走这条路的朋友上一套语义层评审流程每周固定过一批新增口径别等系统上线后再来补课那时候成本会高得多。5.5 经验沉淀如果要重来一遍我会怎么做如果有机会把这两代引擎重做一遍我大概率会从一开始就按“AI交互 语义层 查询执行器”的架构来做而不是先做低代码配置器再迁移。道理很简单配置器的交互设计、查询树结构和字段权限体系虽然有一部分能复用但大量工作其实是在“兜底操作复杂度”上这些到了AI交互阶段基本都用不上。比较理想的方式是先花时间梳理出稳定的语义层再直接建一个支持自然语言查询的轻量前端用AI交互做默认入口把低代码配置器降级成“高级用户可选模式”。当然这个结论是我们已经趟过一遍水才得出的如果你现在还在低代码阶段也不必急着推倒重来先把那套语义层整理清楚AI这件事什么时候接都不晚。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价