本文首发于 Aloudata 官方技术博客：《指标平台选型对比：NoETL 语义编织 vs 传统 ETL/ELT，如何破解数据分析不可能三角？》转载请注明出处。摘要：本文深入对比了传统 ETL/ELT 模式与 Aloudata CAN NoETL 语义编织平台在数据工程领域的核心差异。通过剖析“数据分析不可能三角”的根源，并从架构、开发、治理、成本四个维度进行技术对比，为数据架构师和决策者提供清晰的指标平台选型框架，旨在解决指标口径混乱、响应迟缓与成本高企的痛点。一、决策背景：为何传统 ETL/ELT 模式陷入“数据分析不可能三角”？在 AI 时代，海量、灵活的分析需求与依赖人工预计算物理宽表的传统数据供给模式之间，矛盾日益尖锐。企业数据团队普遍陷入一个痛苦的“不可能三角”：在“业务灵活性”、“指标口径一致性”和“性能成本”三者间，只能艰难取舍，难以兼顾。“指标口径统一说简单真不简单……财务部和销售部都在用‘收入’这个词，但你问问他们怎么算‘收入’——一个是‘含税’，一个是‘不含税’……老板看到两个部门的‘收入’差了几十万，脸色有多精彩吗？” —— 来源：FineBI 技术社区， 2025痛点表现具体如下：口径混乱，数据打架：指标逻辑硬编码在分散的 ETL 脚本和物理宽表中，导致“同名不同义”。例如，财务与运营的“GMV”定义不同，管理层决策无所适从。响应迟缓，敏捷缺失：一个新分析需求，从业务提出到数据团队排期、开发（ODS→DWD→DWS→ADS）、测试、上线，往往需要数周甚至数月。业务创新被冗长的开发链路拖累。分析固化，下钻困难：分析路径被预建的物理宽表（ADS 层）固化。若业务想从“按省份看销售额”下钻到“按城市看”，而宽表未预先聚合城市粒度，则无法实现，灵活性极差。成本高企，资源浪费：为保障报表查询性能，数据工程师不得不预建大量汇总宽表。相同明细数据被反复加工、存储，形成巨大的存储冗余与计算浪费，ADS 层日益臃肿。根因剖析：这一切的根源在于传统“物理宽表驱动”的范式。业务需求必须翻译为具体的物理表结构变更，通过人工编写 ETL/SQL 来实现。这导致了漫长的开发链路、业务与技术的沟通鸿沟，以及任何变更都牵一发而动全身的维护复杂性。引入“不可能三角”：传统模式迫使企业在三角中做出选择：要灵活分析（多建宽表）就会推高成本和加剧口径混乱；要保证口径一致和低成本（少建宽表）就会牺牲查询性能和业务灵活性。这个结构性矛盾，是当前企业数据价值释放的核心瓶颈。二、核心差异：从“物理宽表驱动”到“语义模型驱动”的范式重构要破解“不可能三角”，必须进行范式层面的革新。Aloudata CAN 的本质是基于 NoETL 语义编织的动态计算引擎，其核心是通过将业务语义与物理存储解耦，从根本上颠覆了传统以物理宽表为核心的指标生产模式。范式要素传统模式 (物理宽表驱动)Aloudata CAN (语义模型驱动)核心对象物理表（DWS/ADS 宽表）语义模型（虚拟业务事实网络）指标定义硬编码在 ETL 脚本中声明式配置（基础度量、业务限定、统计周期、衍生计算）开发动作编写 SQL/代码，物理建表零代码配置，系统自动生成 & 优化 SQL治理时机事后人工核对与文档管理事前自动判重，定义即治理架构特征烟囱式，为报表建表平台化，一处定义，处处服务Aloudata CAN 的工作机制：统一语义层：在干净的 DWD 明细数据层之上，通过声明式方式配置业务实体间的逻辑关联，构建一个“虚拟业务事实网络”。无需预先进行物理打宽。定义即开发：业务人员或数据工程师通过界面，像搭积木一样配置指标的四大语义要素（如“近 30 天”、“成功支付的”、“日均交易金额”），平台自动生成最优执行 SQL，实现零代码开发。定义即治理：在定义指标时，系统自动进行全局判重和一致性校验，确保同一个业务概念在全公司只有唯一、权威的定义，从源头杜绝口径不一。范式结论：这场变革是从“为特定报表去建物理表”的被动、烟囱式开发，转向“基于统一的语义模型按需计算”的主动、敏捷响应。三、四维深度对比：技术实现、业务效能与总拥有成本下面我们从四个关键维度，系统化对比两种技术路径带来的截然不同的业务结果。综合对比表对比维度传统 ETL/ELT 模式Aloudata CAN NoETL 语义编织对业务的影响核心架构依赖预计算的物理宽表（DWS/ADS层）统一语义层，直接基于 DWD 明细构建虚拟业务网络摆脱“为报表建表”的束缚，支持任意维度下钻与灵活分析开发模式手工编写、调试 ETL/SQL 脚本，流程冗长定义即开发：配置化声明指标，系统自动生成优化 SQL需求响应从数周缩短至分钟级，业务自助成为可能口径治理指标分散在不同数据集，依赖人工文档与沟通对齐定义即治理：一处定义，处处使用，创建时自动判重实现企业级指标口径100%一致，根治“数据打架”性能与成本为保障查询性能，需预建大量汇总表，导致存储冗余与计算浪费智能物化加速：基于声明式策略，系统自动路由至最优物化结果释放1/3+服务器资源，TCO显著降低，实现亿级数据秒级响应权威背书与客户验证：某头部券商（平安证券）：引入后，指标开发效率提升 10 倍（取数周期从 2 周缩短至 1 天），指标口径实现 100% 一致，基础设施成本节约 50%。某全球连锁餐饮巨头（麦当劳中国）：管理 8 大主题 1000+ 指标，在百亿级数据规模下，查询性能 P90 < 1 秒，日均支撑百万级 API 调用，实现了实时业绩监控与敏捷决策。某头部股份制银行：沉淀 1 万+ 指标，查询性能 <3 秒占比达 95%，数据交付效率提升 10 倍。四、选型决策指南：你的企业更适合哪条路径？选型决策应基于企业当前的数据成熟度、团队能力、业务诉求及战略规划进行综合判断。优先选择 Aloudata CAN 的场景：业务需求变化快：市场、运营等部门需要频繁进行探索性、灵活的分析，追求敏捷响应和实时决策。深受指标治理之苦：企业内存在明显的“数据打架”现象，部门间因指标口径不一协同低效，管理层需要唯一可信的数据源。希望提升团队效能：希望降低对稀缺的、专注于编写 ETL 脚本的数据工程师的依赖，赋能业务人员实现自助分析。关注长期 TCO 与架构现代化：希望优化数据架构，降低冗余存储与计算成本，并为未来 AI 应用构建坚实的 AI-Ready 数据底座。数字化初期企业：希望跳过“先乱后治”的痛苦阶段，直接采用先进的“语义模型驱动”架构，实现“弯道超车”和“数字化平权”。可能暂缓考虑的场景：现有基于宽表的报表体系非常稳定，且未来一段时间内无新的、灵活的分析需求。技术团队资源充足，且已深度绑定并熟练使用特定的传统 ETL 工具链，业务对数据时效性要求极低（如 T+1 以上）。落地策略建议：平滑演进“三步走”对于大多数企业，我们推荐采用平滑演进策略，而非颠覆式重建：存量挂载：将逻辑成熟、性能稳定的现有宽表直接挂载到平台，统一纳管口径，保护历史投资。增量原生：所有新产生的分析需求，坚决采用“增量原生”模式，直连 DWD 明细层通过语义定义敏捷响应，从源头遏制宽表继续膨胀。存量替旧：逐步将那些维护成本高、逻辑复杂、资源消耗巨大的“包袱型”旧宽表替换下线，迁移至语义模型。五、常见问题 (FAQ)Q1: 我们已经使用了现代云数仓，为什么还需要 Aloudata CAN 这样的语义编织层？现代云数仓是强大的“存储与计算引擎”，解决了弹性伸缩问题。但业务灵活分析的需求，仍然需要通过人工开发大量物理宽表来满足，这导致了“最后一公里”的口径混乱和成本浪费。Aloudata CAN 是在这些强大引擎之上，构建统一、敏捷的“业务语义层”和“智能物化加速器”，让好引擎能持续、高效地产出可信、好用的数据，根治指标不一致问题。Q2: 采用 NoETL 语义编织，是否意味着我们要完全抛弃和重写现有的 ETL 流程与宽表？并非如此。推荐采用“存量挂载+增量原生”的混合策略。对于逻辑成熟、性能尚可的现有宽表，可以零代码直接挂载到平台，统一口径管理，保护历史投资。对于所有新产生的分析需求，则坚决采用“增量原生”模式，直连 DWD 明细层通过语义定义敏捷响应，从源头遏制宽表继续膨胀，并逐步将高维护成本的旧宽表替换下线。Q3: Aloudata CAN 如何保证复杂业务指标计算的准确性，避免 AI 问数时的“幻觉”问题？平台通过 NL2MQL2SQL 架构根治幻觉。当 AI 或用户用自然语言提问时，大模型只负责意图理解并生成标准的指标查询语言（MQL），然后由平台的语义引擎将 MQL 翻译为 100% 准确的优化 SQL。这相当于将“写代码”的开放题变成了“选指标”的选择题，极大收敛了搜索空间，确保了结果基于企业唯一权威的指标定义生成，同时结合行列级权限保障数据安全。Q4: 引入新平台后，我们现有的数据团队角色和技能要求会发生什么变化？这是积极的角色转型。数据工程师将从重复、低价值的 SQL 脚本编写和 ETL 任务运维中解放出来，转向更具战略性的工作：设计与优化企业级语义模型、保障数据供应链质量、配置与优化智能物化策略、以及赋能业务人员进行自助分析。平台提供直观界面，团队可以较快适应新角色，提升整体价值与影响力。六、核心要点范式革新是根本：传统“物理宽表驱动”的 ETL/ELT 模式是“数据分析不可能三角”的根源。Aloudata CAN 的“语义模型驱动”范式，通过逻辑与物理解耦，是打破三角的根本性架构革新。价值可量化验证：领先企业的实践表明，新范式能带来指标口径 100% 一致、需求响应从数周缩短至分钟级、以及释放 1/3+ 服务器资源的直接业务价值。选型需对标场景：业务需求多变、深受口径不一致之苦、追求降本增效及 AI 就绪的企业，是 NoETL 语义编织平台的理想受益者。落地可平滑演进：通过“存量挂载、增量原生、存量替旧”的三步走策略，企业可以在保护现有投资的同时，稳健地向现代化数据架构演进。战略上构建 AI 底座：统一的语义层不仅是提升 BI 效率的工具，更是企业构建高质量、结构化、易被 AI 理解的 AI-Ready 数据底座的关键基础设施。*本文完整版及高清图表，请访问 Aloudata 官方技术博客阅读：https://ai.noetl.cn/knowledge-base/aloudata-can-semantic-weav...
指标平台选型关键与 Aloudata CAN 无宽表计算方案
本文首发于 Aloudata 官方技术博客：《指标平台选型关键：告别宽表依赖，Aloudata CAN 如何定义复杂指标？》转载请注明出处。摘要：本文深入探讨了在数据工程实践中，面对“近7天高价值用户数”等复杂指标时，传统宽表模式的局限性。通过对比传统静态宽表计算与 Aloudata CAN NoETL 指标平台的动态语义编织架构，从指标定义能力、分析灵活性、AI适配性等维度，为数据架构师和决策者提供一套清晰的选型决策框架，旨在帮助企业破解数据分析的性能、灵活性与成本之间的“不可能三角”。一、决策背景：当复杂指标需求撞上“宽表依赖症”数据团队对以下场景绝不陌生：业务方提出“近 7 天支付金额大于 100 元的去重用户数”这类指标，分析师在 BI 工具中拖入一个新的维度组合，查询响应时间便从秒级骤降至分钟级，甚至触发超时。其根源在于，传统的“数仓+宽表+BI”模式在面对灵活多变的复杂业务逻辑时，存在结构性瓶颈，即“宽表依赖症”。“宽表依赖症”的核心困境体现在：开发效率低：为应对“指标转标签”（如“上月交易量 > 0 的用户”）或“多层嵌套聚合”（如“月日均交易额最大值”）等复杂逻辑，数据工程师需编写数百行 SQL，构建物理宽表。需求排期以周甚至月计，无法支持业务快速迭代。分析不灵活：分析路径被预建的物理宽表（ADS 层）所固化。一旦业务提出未预见的维度组合（如新增“用户等级”维度），就必须启动新一轮的宽表开发排期，严重制约了业务探索性分析。成本高昂：为满足不同分析场景，大量宽表和汇总表被重复开发，导致存储与计算资源严重浪费，形成“烟囱式”的数据资产。“在指标平台等分析场景下，数据量往往达到亿级甚至更高。查询缓慢、响应延迟成为常态，严重影响了业务人员获取数据的时效性。” —— 镜舟科技技术博客这种模式在追求极致分析性能、灵活性和成本效益之间难以找到平衡点，构成了数据分析的“不可能三角”。二、核心差异：静态宽表计算 vs 动态语义编织性能与灵活性困境的根本差异，源于底层架构的范式革新。传统模式（静态宽表计算）：其核心是 “预计算、后查询” 。数据分析师或开发人员需要预先理解业务需求，编写 SQL 或 ETL 任务，将多张表打平成物理宽表或汇总表。查询时，BI 工具直接访问这些固化好的物理表。其性能上限在宽表创建时即被锁定，且无法应对未预见的查询模式。Aloudata CAN NoETL 模式（动态语义编织）：其核心是 “声明定义、动态计算” 。基于语义编织技术，用户在界面通过 声明式策略 完成两件事：声明逻辑关联：在未打宽的 DWD 明细表之间，声明业务实体间的关联关系（如 订单表 JOIN 用户表）。声明指标逻辑：通过配置“基础度量、业务限定、统计周期、衍生计算”四大语义要素来定义指标。系统据此在逻辑层构建一个 虚拟业务事实网络（或称虚拟明细大宽表）。当业务发起查询时，语义引擎 将查询意图翻译为最优化的 SQL，并通过 智能物化引擎 透明路由至已预热的物化结果或高效执行原生查询。这是一种 “逻辑定义与物理执行解耦” 的架构。三、维度对比一：复杂指标定义能力面对复杂的业务逻辑，两种模式在定义方式、效率和维护性上存在天壤之别。对比维度传统宽表模式Aloudata CAN NoETL 模式定义方式编写数百行 SQL，人工开发，依赖资深工程师声明式配置，零代码定义，业务分析师即可完成典型场景简单聚合（如销售额、订单数）指标转标签（如“上月交易>0的用户”）、多层嵌套聚合（如“月日均最大值”）、跨表复合指标（如“渠道ROI”）开发效率低，需求排期以周/月计，响应迟缓高，分钟级完成定义与交付，实现业务自助维护成本高，逻辑变更需重写 SQL 与 ETL，牵一发而动全身低，配置化修改，系统自动同步所有下游，治理内嵌于流程核心差异解读：传统模式将复杂的业务逻辑固化在物理表结构中，变更成本极高。而 Aloudata CAN 通过语义抽象，将指标转化为可配置的要素，实现了 “定义即开发” 。例如，定义“近 30 天有购买行为的用户”这一标签，只需选择“交易金额”作为基础度量，设置“统计周期”为近 30 天，“业务限定”为“交易金额 > 0”，系统即自动生成并执行相应的去重计数逻辑，无需编写一行 JOIN 和 GROUP BY 的 SQL。四、维度对比二：分析灵活性与性能保障当业务需要自由探索数据时，两种架构对分析路径和查询性能的保障机制截然不同。传统模式：分析灵活性被物理宽表预先定义好的维度组合所限制。任何未预见的查询都可能导致性能“开盲盒”，直接扫描亿级明细，响应时间无法保障。Aloudata CAN：支持指标与维度任意组合、自由下钻。其性能通过 声明式物化策略 保障：用户可声明对特定指标和维度组合进行加速，系统据此自动编排物化任务并维护物化视图（预汇总结果）。查询时，智能物化引擎 自动进行 SQL 改写和路由，透明命中最优物化结果，实现热点查询的秒级响应。这种性能已在客户实践中得到验证。例如，某全球连锁餐饮巨头 在 Aloudata CAN 上沉淀了 8 大主题 1000+ 指标、250+ 维度，面对百亿级数据规模，实现了 P90 响应时间 < 1 秒，日均稳定支撑百万级 API 调用，彻底解决了性能与灵活性的矛盾。五、维度对比三：AI 适配与未来扩展性AI 时代，尤其是对话式数据分析（ChatBI）的兴起，对数据的语义一致性和接口确定性提出了更高要求。传统模式：无法为 AI 提供统一的、业务友好的语义接口。大模型（LLM）直接面对杂乱无章的物理表生成 SQL，极易产生“数据幻觉”，且无法进行有效的权限管控。Aloudata CAN：原生 AI-Ready，其核心是 NL2MQL2SQL 架构：NL2MQL：LLM 负责理解用户自然语言问题，并生成标准的指标查询语言（MQL），这是一个收敛了搜索空间的“选择题”。MQL2SQL：语义引擎 将 MQL 翻译为 100% 准确的、经过优化的 SQL，并利用智能物化引擎加速。安全层：请求先经语义层鉴权，验证通过后才执行，杜绝 AI 越权访问，实现“先安检，后执行”。作为 《数据编织数据虚拟化平台技术要求》等标准的核心起草单位，Aloudata CAN 的语义层本质上是一个高度浓缩的业务知识图谱，为 RAG（检索增强生成）提供了最佳语料，确保 AI 能以极低的成本获得极高的上下文精准度，从源头根治幻觉。六、综合选型建议：基于企业数据成熟度决策没有“最好”的平台，只有“最适合”当前阶段和未来需求的平台。决策应基于企业的数据规模、业务灵活性需求及 AI 战略。决策路径参考：场景 A（数据量 < 千万级，报表需求固定）特征：数据量小，业务分析维度相对固化，暂无 AI 问数需求。建议：传统数仓宽表模式或主流 BI 工具内置的数据集仍可有效应对，引入自动化平台的投资回报率（ROI）可能不高。场景 B（数据量达亿级或更高，业务查询需求灵活多变）特征：面临“宽表依赖症”的典型痛点，业务希望自由下钻分析，但对查询延迟敏感。建议：强烈建议评估 Aloudata CAN 这类 NoETL 指标平台。其动态语义编织和智能物化加速能力，能在保障秒级响应的同时，提供极大的分析灵活性，从根本上破解性能与灵活性的矛盾。可参考 某头部券商 的实践：实现开发效率 10 倍提升，基础设施成本节约 50%。场景 C（高并发查询 + AI 智能问数需求）特征：需要面向大量业务用户或应用系统提供稳定、统一的数据服务，并计划引入自然语言查询数据。建议：必须选择具备 NL2MQL2SQL 能力的 AI-Ready 数据底座。Aloudata CAN 的语义层为 AI 提供了精准、安全的唯一指标化访问接口，是构建可靠数据智能应用的必备基础。对于数字化初期的企业，采用 NoETL 架构更是一种 “弯道超车” 的机会，能跳过“先乱后治”的传统数据建设阶段，直接构建统一、敏捷的数据服务能力。七、常见问题 (FAQ)Q1: 什么是“无宽表计算”？它如何保证查询性能？“无宽表计算”指不依赖预建的物理宽表，而是通过语义编织技术在逻辑层构建虚拟业务事实网络。性能通过 “智能物化加速引擎” 保障：基于用户声明的加速策略，系统自动创建并维护物化视图（预汇总结果），实现热点查询的透明加速，达到亿级数据秒级响应（P90<1s, P95<3s）。Q2: Aloudata CAN 能处理哪些传统宽表难以定义的复杂指标？主要支持四大类：1) 指标转标签（如“近30天有购买行为的用户”）；2) 时间维度多次聚合（如“月日均交易额最大值”）；3) 跨表复合指标（如“渠道ROI”，需关联订单表与营销费用表）；4) 自定义周期指标（如“近5个交易日”）。这些均可通过配置化实现，无需编写复杂 SQL。Q3: 引入 NoETL 指标平台，对现有数仓架构和团队工作方式有何影响？影响是正向优化的：1) 架构上：做轻数仓，减少 ADS 层冗余宽表开发，直接基于 DWD 明细层工作，释放存算资源。2) 团队协作上：形成“科技定义原子指标 -> 分析师配置派生指标 -> 业务自助分析”的新模式，极大提升整体效率，释放数据工程师生产力。Q4: 如何开始评估和试用 Aloudata CAN？建议从明确的业务场景切入，如“营销活动效果分析”或“核心业务日报”。Aloudata 提供技术对接支持，可快速接入企业现有数据湖仓，在 1-2 周内完成价值验证（PoC），亲眼见证复杂指标的定义速度与查询性能。八、核心要点总结架构范式革新：选型的核心是区分 “静态宽表计算” 与 “动态语义编织” 。前者预计算、后查询，灵活性锁死；后者声明定义、动态计算，实现逻辑与物理解耦。破解不可能三角：NoETL 模式通过 统一语义层 和 智能物化加速，能同时实现指标口径 100% 一致、分析灵活任意下钻、以及亿级数据秒级响应，破解传统方案的性能、灵活性与成本困境。面向未来的 AI-Ready 底座：构建企业级数据智能，必须选择具备 NL2MQL2SQL 能力的指标平台，为 AI 提供确定性的语义接口，从源头根治数据幻觉，并确保查询的合规与安全。明确的选型路径：决策应基于数据规模与业务需求。对于数据量达亿级且需求多变的企业，评估 NoETL 指标平台是提升数据敏捷性和释放工程生产力的关键一步。*本文为技术解析与选型指南，更多技术细节、产品演示及客户案例，请访问 Aloudata 官方技术博客阅读原文：https://ai.noetl.cn/knowledge-base/aloudata-can-complex-metri...
写给技术管理者的低代码手册系列文章（2）——第一部分：低代码诞生的背景
第一章 企业软件复杂度的逐步累积1.1 从硬件导向到数据导向早期的软件开发几乎完全围绕计算机硬件展开。机器语言与汇编语言要求开发者理解CPU指令、寄存器和内存地址，软件的表达方式高度依赖具体硬件体系结构，如SSE指令集中用于比较字符串的pcmpistr，无法运行在不支持SSE的CPU上。这一阶段的软件极其昂贵、开发周期漫长、可复用性极低，应用范围也因此被限制在政府、科研机构和少数大型企业的核心场景中。随着电子工业的发展，计算机开始进入企业管理领域。跨行业、跨规模推广计算机应用的关键，在于找到一种足够通用的抽象方式。1970年，来自IBM的E.F.Codd博士在ACM通讯杂志上发表的论文《大规模共享数据银行的关系型模型》，为解决这一问题提供了一种切实可行的技术路线。该路线中，现实世界中的业务单据、业务流程和管理决策，被统一抽象为数据的存储、处理与分析，而执行这些操作的软件被统称为“关系型数据库”。企业的用户只需要一个连接到数据库软件的终端，就能用一套近似于英语的、统一的语言来操作这个软件，以此实现所有的业务操作。如用户想要查询姓名中包含“李”的员工档案，需要输入 SELECT * FROM STAFFS WHERE NAME LIKE ‘%李%’ ，界面上就会呈现出纯文本呈现的员工档案信息。图：早期的数据库服务器与操作终端关系型数据库的出现，标志着企业软件第一次在抽象层面实现了规模化。通过关系模型描述业务实体及其关系，通过统一的数据操作语言处理不同业务场景，数据库成功降低了企业信息化的技术门槛，也显著扩展了软件需求的边界。1.2 “壳”的出现与复杂度外溢当数据库从档案管理走向财务、库存、成本核算等复杂业务场景时，一个新的问题随之出现：直接操作SQL对最终用户并不友好，一个业务操作需要多次打印和重复输入，导致操作员工作负荷高、出错概率大。为此，行业选择将数据库抽象为数据模型（数据模型可近似理解为数据库的结构，由数据表、列和表关系构成），在模型之上构建应用软件。这种做法很像是给数据库“套壳”，让用户操作应用，应用去操作数据库，而非用户直接操作数据库。这一决策带来了企业软件形态的根本变化。业务逻辑开始在数据库与应用程序之间重新分配，用户交互界面成为差异化竞争的核心。随着抽象度更高的新一代高级语言（如C++、Java语言）在应用层的普及，企业软件正式进入“高级语言 + 数据库”的长期技术范式。图：DOS时代的企业软件操作界面然而，这种分层结构也埋下了复杂度累积的种子：数据模型持续膨胀：一个小型订单管理系统可能只有十几张表，但经过几年演进后，堪比ERP的系统重，表数量可能增长到数百张业务规则不断叠加：每次业务流程调整都会增加新的验证规则、计算公式和例外处理逻辑交互逻辑日益复杂：从简单的表单录入发展到复杂的向导流程、多标签页面和实时校验应用规模和生命周期显著拉长：企业软件往往需要运行十年甚至更长时间，期间不断打补丁和加功能企业软件不再是一次性交付的工具，而是需要多年演进、持续维护的复杂系统。扩展链接写给技术管理者的低代码手册系列文章（1）——从软件工程视角理解低代码的价值、边界与演进路径
前面的章节（社区专栏《SQL调优》）我们已经写了很多篇幅关于 MySQL 执行计划的解读，今天我们来继续延伸介绍执行计划的链路跟踪功能，也就是 MySQL 的 Optimizer Trace。在这之前，先来回顾下 EXPLAIN 的结果：mysql:ytt>explain select * from t1 a left join y1 b on a.id = b.id where a.r1<100 order by a.r2 desc; +----+-------------+-------+------------+--------+---------------+---------+---------+----------+--------+----------+-----------------------------+ | id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------+------------+--------+---------------+---------+---------+----------+--------+----------+-----------------------------+ | 1 | SIMPLE | a | NULL | ALL | idx_r1 | NULL | NULL | NULL | 998222 | 50.00 | Using where; Using filesort | | 1 | SIMPLE | b | NULL | eq_ref | PRIMARY | PRIMARY | 4 | ytt.a.id | 1 | 100.00 | NULL | +----+-------------+-------+------------+--------+---------------+---------+---------+----------+--------+----------+-----------------------------+ 2 rows in set, 1 warning (0.00 sec)EXPLAIN 展示出来的核心数据有：表关联顺序优化器筛选过的索引实际使用的索引每张表依据统计信息的扫描行数Extra 额外数据提示两种执行计划（explain format=tree / explain format=json）展示出来的额外成本数据如果想快速对于 SQL 进行优化，基于以上的结果完全可以满足。但是想深入了解 MySQL 优化器为什么选择这样的执行计划，基于以上的结果就无法满足。举例说明：我想知道对于表 a 来讲，为什么有索引 idx_r1，但是实际却没有使用，而走的全表扫？两张表关联，为什么选择的顺序是表 a 驱动表 b，而不是表 b 驱动表 a？为什么字段 r2 有索引，但是依然要走排序？带着这些疑问，我们来介绍 MySQL 的 Optimizer Trace 功能。1. 什么是 Optimizer Trace？简单来讲，Optimizer Trace 是一个 SQL 执行计划的链路跟踪器，跟踪 SQL 的解析、优化、执行等过程，并且把结果记录到 MySQL 元数据表（information_schema.optimizer_trace），之后可以对这张表分析得到很多个执行计划的“为什么？”！2. 如何使用 Optimizer Trace？要使用 Optimizer Trace 功能，首先得打开控制开关。谨记：这个功能非常耗费资源，默认关闭的，可以通过调整以下变量开启：mysql:ytt>show variables like 'optimizer_trace%'; +------------------------------+----------------------------------------------------------------------------+ | Variable_name | Value | +------------------------------+----------------------------------------------------------------------------+ | optimizer_trace | enabled=off,one_line=off | | optimizer_trace_features | greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on | | optimizer_trace_limit | 1 | | optimizer_trace_max_mem_size | 1048576 | | optimizer_trace_offset | -1 | +------------------------------+----------------------------------------------------------------------------+ 5 rows in set (0.00 sec)以上几个参数详细解释下：optimizer_trace：enabled=on/off 启用/禁用 Optmizer Trace 功能；one_line=on/off 启用/禁用 json 格式化存储，一般不需改动。optimizer_trace_limit/optimizer_trace_offset：这两个参数和 LIMIT 子句一样，用来最终展示 Trace 的 SQL 条数。展示的条数越多，对内存消耗越大，默认展示最近的一条记录。比如设置 optimizer_trace_limit 为 10，optimizer_trace_offset 为 -10，就可以最多展示 10 条 Trace 记录。optimizer_trace_max_mem_size：用来存储 Trace 结果的最大内存。optimizer_trace_features：用来启动/禁用相关 Trace 特性开关。end_markers_in_json：启用/禁用 注释功能。开启这个，Trace 结果可读性更强。Optimizer Trace 可以跟踪的语句有：SELECT、TABLE、VALUES、WITH、INSERT、REPLACE、UPDATE、DELETEEXPLAINSET（排除设置 Optimizer Trace 相关参数）DO存储函数内部、触发器内部等的 DECLARE、CASE、IF、RETURN 语句CALL在数据库里，语句调优一般说的是 SELECT 语句，所以大部分场景跟踪的也只有 SELECT 语句。元数据表字段解析mysql:ytt>desc information_schema.optimizer_trace; +-----------------------------------+----------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------------------------------+----------------+------+-----+---------+-------+ | QUERY | varchar(65535) | NO | | | | | TRACE | varchar(65535) | NO | | | | | MISSING_BYTES_BEYOND_MAX_MEM_SIZE | int | NO | | | | | INSUFFICIENT_PRIVILEGES | tinyint(1) | NO | | | | +-----------------------------------+----------------+------+-----+---------+-------+ 4 rows in set (0.00 sec)QUERY：TRACE 的 SQL 语句原文TRACE：SQL 语句的 TRACE 结果，JSON 格式存储（由变量 end_markers_in_json 来控制）MISSING_BYTES_BEYOND_MAX_MEM_SIZE：TRACE 结果超过变量 optimizer_trace_max_mem_size 设置的值后，截断的大小（BYTE）INSUFFICIENT_PRIVILEGES：对存储过程、存储函数等包含有 SQL SECURITY DEFINER 的用户是否有对应的权限，有权限为 0，无权限为 1，并且 TRACE 字段为空。Optimizer Trace 开启步骤mysql:ytt>set optimizer_trace='enabled=on'; Query OK, 0 rows affected (0.00 sec) mysql:ytt>set optimizer_trace_limit=10; Query OK, 0 rows affected (0.00 sec) mysql:ytt>set optimizer_trace_offset=-10; Query OK, 0 rows affected (0.00 sec) mysql:ytt>set end_markers_in_json=on; Query OK, 0 rows affected (0.00 sec)这里要注意的是，修改任何一个 Optimizer Trace 相关参数，元数据表 information_schema 表都会被清空。mysql:ytt>select count(*) from information_schema.optimizer_trace; +----------+ | count(*) | +----------+ | 10 | +----------+ 1 row in set (0.00 sec) mysql:ytt>set optimizer_trace_offset=-2; Query OK, 0 rows affected (0.00 sec) mysql:ytt>select count(*) from information_schema.optimizer_trace; +----------+ | count(*) | +----------+ | 0 | +----------+ 1 row in set (0.00 sec)3. Optimizer Trace 的结果我们用一个最简单的例子来看看 Optimizer Trace 的大致结构：do 语句非常简单，只用来验证是否语法正确，不出结果。mysql:ytt>do 1+1; Query OK, 0 rows affected (0.00 sec)下面是 Optimizer Trace 结果：mysql:ytt>select query,trace from information_schema.optimizer_trace\G *************************** 1. row *************************** query: do 1+1 trace: { "steps": [ { "join_preparation": { "select#": 1, "steps": [ { "expanded_query": "/* select#1 */ select (1 + 1) AS `1+1`" } ] } }, { "join_optimization": { "select#": 1, "steps": [ ] } }, { "join_execution": { "select#": 1, "steps": [ ] } } ] } 1 row in set (0.00 sec)可以看到，Optimizer Trace 结果是一个 JSON 串，key 为 steps，value 是一个数组，数组有三个 key，分别为：join_preparation 准备阶段：这里会做一些 SQL 改写，关键字识别等等，可以看到 expanded_query 对应的值即为 SQL 语句被改写后的内部 SQL。join_optimization 优化阶段：具体 SQL 优化，包括一些可能的逻辑优化，一些根据表统计信息预估的物理优化等等。join_execution 最终执行阶段：最终 SQL 采用的执行计划等等。本篇是Optimizer Trace的开端，由于内容太多，我特地拆分为几篇来写，欢迎继续订阅。
BigQuery 新功能：SQL 直调 17 万 + AI 模型，3800 万行数据处理成本仅 2 美元
Google 近期针对 BigQuery 推出了面向开源模型的第三方生成式 AI 推理功能。这一更新允许数据团队直接使用简单的 SQL 语句，部署并运行来自 Hugging Face 或 Vertex AI Model Garden 的任何模型。该接口目前处于预览阶段，其最大的亮点在于消除了对独立机器学习（ML）基础设施的需求，系统会自动启动计算资源、管理端点，并在任务完成后通过 BigQuery 的 SQL 接口自动清理资源。这项新功能解决了困扰数据团队已久的痛点。在过去，运行开源模型往往意味着需要管理 Kubernetes 集群、配置端点以及在多种工具之间反复切换。Virinchi T 在一篇关于此次发布的 Medium 文章中指出：这一过程需要多种工具协同、不同的技能储备以及巨大的运维开销。对于许多数据团队来说，这种摩擦意味着即便模型本身是免费且公开的，AI 能力依然显得遥不可及。然而，得益于 BigQuery 的 SQL 接口，整个工作流现在被简化为仅需两条 SQL 语句。用户首先通过一条 CREATE MODEL 语句来创建模型，只需指定 Hugging Face 的模型 ID（例如 sentence-transformers/all-MiniLM-L6-v2）或 Vertex AI Model Garden 中的模型名称。BigQuery 会根据默认配置自动分配计算资源，部署过程通常在 3 到 10 分钟内即可完成，具体时长取决于模型大小。部署完成后，用户可以使用 AI.GENERATE_TEXT（针对语言模型）或 AI.GENERATE_EMBEDDING（针对嵌入模型）直接对 BigQuery 表中的数据进行推理查询。平台通过 endpoint_idle_ttl 选项管理资源的生命周期，该功能会自动关闭闲置端点以节省费用。此外，在批处理任务结束后，用户还可以通过 ALTER MODEL 语句手动卸载端点。为了满足生产环境的需求，该功能还支持高度定制化。用户可以直接在 CREATE MODEL 语句中设定机器类型、副本数量以及端点闲置时间。通过 Compute Engine 预留功能，还可以锁定 GPU 实例以确保性能稳定。当不再需要某个模型时，只需执行一条简单的 DROP MODEL 语句，系统便会自动清理所有关联的 Vertex AI 资源。Google 在官方博客中将该系统描述为提供“精细的资源控制”和“自动化的资源管理”，旨在让团队在不脱离 SQL 环境的情况下，找到性能与成本之间的最佳平衡点。2025 年 9 月发布的一篇早期博客曾展示，利用类似的开源嵌入模型处理 3800 万行数据，成本仅需约 2 到 3 美元。目前，该功能已支持超过 1.3 万个 Hugging Face 文本嵌入模型和超过 17 万个文本生成模型，涵盖了 Meta 的 Llama 系列和 Google 的 Gemma 家族。需要注意的是，所选模型必须符合 Vertex AI Model Garden 的部署要求，包括区域可用性和配额限制。Virinchi T 强调了这一变革对不同角色的意义：对于数据分析师而言，你现在可以无需离开 SQL 环境，也不必等待工程资源支持，就能直接实验 ML 模型。对于数据工程师而言，构建由机器学习驱动的数据管道变得极其简单，再也不用维护独立的 ML 基础设施。此次发布标志着 BigQuery 将与 Snowflake 的 Cortex AI 以及 Databricks 的 Model Serving 展开直接竞争，后两者同样提供基于 SQL 的 ML 推理能力。而 BigQuery 的竞争优势可能在于其与 Hugging Face 庞大模型库在数据仓库内的深度集成，这对于已经在 Google Cloud 上运行业务的用户具有极强的吸引力。目前，关于 Gemma 模型的文本生成以及嵌入生成的相关文档和教程已正式上线。原文链接：https://www.infoq.com/news/2026/01/bigquery-sql-huggingface-managed/
数据工程视角：为什么公司会有几百个含义模糊的“DAU”指标？
本文首发于 Aloudata 官方技术博客：《为什么公司会有几百个含义模糊的“DAU”指标？深度解析》转载请注明出处。摘要：企业数据治理中普遍存在数百个同名不同义的“DAU”指标，这并非管理失误，而是传统“数仓+BI”烟囱式架构的必然结果。本文将从数据工程视角，精确定义指标口径混乱的四大要素，剖析其三大结构性根源，并阐述如何通过构建基于 NoETL 语义编织技术的统一指标平台，实现“一次定义，处处使用”，从根本上解决数据分析的“不可能三角”难题。“数据孤岛导致的‘同源不同口径’问题日益严重。不同业务系统独立运行，产生的数据没有统一的描述体系。结果就是：明明是同一个‘活跃用户’指标，财务、市场和运营的口径却完全不同。这会直接导致数据驱动的决策不一致。” —— 行业分析报告当一家企业的数据团队发现，他们维护着数百个名为“DAU”（日活跃用户）或“销售额”的指标，而每个指标的计算逻辑、统计周期或业务限定都略有不同时，这通常不是某个部门或个人的失误。相反，这是传统数据架构模式下的一个必然结果。在经典的“数仓+BI”模式中，业务需求驱动着漫长的物理开发链路：一个报表需求 → 数据工程师开发 ETL 任务 → 创建特定的物理宽表（DWS/ADS 层） → BI 工具连接该宽表生成报表。这种“为特定报表建特定宽表”的烟囱式开发，将指标逻辑固化并分散在了成百上千个物理表中。每一次新的分析视角，都可能催生一张新的宽表和一个“略有不同”的指标版本。这直接导致了数据分析的“不可能三角”：在口径一致、响应敏捷和深度洞察三者之间难以兼得。精确定义：什么才是真正的“指标口径混乱”？指标口径混乱并非一个模糊的概念，它特指同一业务术语在不同数据消费场景中，其核心语义要素存在不一致，从而导致决策依据相互矛盾。一个完整的指标定义包含四大语义要素，任何一处的差异都可能导致“混乱”：基础度量：核心的聚合计算，如COUNT(DISTINCT user_id)、SUM(order_amount)。统计周期：数据统计的时间范围，如“当日”、“近7日滚动”、“本财年至今”。业务限定：对数据范围的筛选条件，如“状态为‘已支付’”、“用户渠道为‘APP’”。衍生计算：基于基础度量的二次计算，如同环比、占比、排名。例如，市场部的“DAU”可能统计所有启动 APP 的设备，而财务部的“DAU”可能只统计完成至少一次有效交易的用户。这不仅仅是“活跃”定义的差异，更是基础度量（是否去重）和业务限定（是否包含交易行为）的双重不一致。核心要素：导致指标泛滥的三大“元凶”指标混乱现象是技术架构、组织协作和工具生态三个层面因素共同作用的“完美风暴”。要素一：烟囱式的物理宽表开发这是最根本的技术原因。每个分析需求都对应一张（或多张）物理宽表，指标逻辑被硬编码在 SQL 和表结构中。当业务规则变更（如“活跃”定义调整）时，需要追溯并修改所有相关的宽表，成本极高且极易遗漏，导致历史数据对比失真。要素二：部门墙与协作断层业务方、数据分析师与数据开发团队之间缺乏统一的协作语言和平台。需求通过邮件、会议口头传递，容易产生歧义。各部门为追求自身效率，在本地数据集或临时查询中定义“自己版本”的指标，形成组织内的“数据方言”。要素三：封闭的 BI 工具内置指标主流 BI 工具为提升易用性，内置了指标定义模块。然而，这些指标定义被绑定在特定的 BI 工具前端。当企业使用多套 BI 工具（如总部用 A，业务部门用 B），或需要向 AI 大模型、自建应用提供数据服务时，这些封闭的指标定义无法被复用，形成了新的“工具孤岛”。常见误区：关于指标治理的四个错误认知许多企业意识到问题，却采用了错误的方法，反而加剧了困境。误区错误本质导致的后果误区一：建一个指标字典就够了将指标治理等同于建立静态的元数据目录（Catalog）。目录与计算脱节，业务人员查阅字典后，仍需找开发人员从物理宽表中取数，口径落地依赖人工，无法保证一致性。误区二：强制统一所有报表采用行政命令，要求所有部门立即废弃原有报表，使用统一模板。忽视业务敏捷性，引发业务部门强烈抵触，治理行动难以推进，甚至催生更隐蔽的“影子报表”。误区三：选择一个BI工具统一天下试图通过采购单一BI厂商的全套方案来解决所有问题。被单一厂商绑定，丧失技术选型灵活性；无法适应不同场景的多样化需求（如 AI 调用、嵌入式分析）。误区四：指标治理是IT部门的事认为制定标准、维护口径是数据团队的技术职责。缺乏业务方的深度参与和共识，制定的标准脱离实际业务场景，治理成果无法在业务决策中落地。企业价值：终结指标混乱带来的四大收益解决指标口径问题，远不止于“统一语言”，它能直接转化为可量化的业务与技术收益。决策一致：基于同一事实决策，彻底避免部门间因数据“对不上”而产生的无谓争论与信任损耗，提升组织协同效率。响应敏捷：业务人员通过自助式拖拽分析，无需等待排期，将分析需求响应周期从“天级”压缩至“分钟级”，快速验证业务假设。洞察深化：突破预建宽表的维度限制，支持对指标进行任意维度、任意粒度的灵活下钻与归因分析，从“描述现象”走向“解释原因”。成本降低：通过做轻数仓，减少甚至消除大量重复的 DWS/ADS 层物理宽表开发与维护，可释放 30% 以上的服务器计算与存储资源。案例佐证：某头部股份制银行通过引入统一指标平台，实现了总分行指标口径 100% 一致，数据交付效率提升 10 倍（从 2 周缩短至 1 天），并沉淀了超过 1 万个可复用的标准指标。评估清单：你的企业是否已陷入指标泥潭？请用以下 5 个问题快速自检：同一个核心业务指标（如“销售额”、“利润率”），财务、市场、运营等部门给出的数字是否经常对不上，需要反复核对？业务部门提出一个新的报表或分析需求，从提出到最终上线，平均排期是否超过 1 周？业务人员能否在不求助数据团队的情况下，自主、灵活地切换分析维度（如从“按地区看”切换到“按产品品类看”）？数据团队是否花费大量时间，疲于维护众多业务逻辑相似但略有不同的汇总表、宽表？当企业引入新的 BI 工具或AI智能问数应用时，是否需要数据团队重新定义、开发一套指标？如果上述问题有两个或以上的答案是肯定的，那么您的企业很可能已经深受指标混乱之苦。解决方案：基于 NoETL 语义编织的统一指标平台要根治上述问题，需要从架构层面进行革新，将指标的定义、计算与服务进行逻辑解耦。这正是 Aloudata CAN NoETL 指标平台的核心。核心理念：定义即开发，定义即服务平台基于 NoETL 语义编织 技术，允许用户在逻辑层面进行声明式定义：逻辑关联声明：在 DWD 明细层上，声明业务实体间的关联关系，构建“虚拟业务事实网络”，无需预先物理打宽。声明式指标定义：通过配置化方式，组合“基础度量、统计周期、业务限定、衍生计算”四大语义要素，零代码定义复杂指标（如“上月高价值用户复购率”）。智能物化加速：基于用户声明的加速策略（而非全自动感知），系统自动生成并维护物化视图，查询时智能路由，实现亿级数据秒级响应。架构对比：从“烟囱林立”到“统一语义层”传统架构（左）：需求驱动，层层物理建模，形成大量 DWS/ADS 宽表，指标逻辑分散且固化。NoETL架构（右）：统一的语义层直接对接 DWD 明细数据，逻辑定义指标，向上通过标准 API/JDBC 服务各类消费端（BI、AI、应用）。关键价值：成为 AI-Ready 的数据底座混乱的指标和元数据是导致AI智能问数产生“幻觉”的主因。统一指标平台通过构建高质量的语义知识图谱，为 AI 提供了精准的上下文。根治幻觉：采用 NL2MQL2SQL 架构。用户用自然语言提问 → LLM 理解意图生成指标查询语言（MQL）→ 平台语义引擎将 MQL 转换为 100% 准确的优化 SQL。安全可控：所有 AI 数据请求先经过语义层鉴权，确保符合行列级数据安全策略，实现“先安检，后执行”。常见问题 (FAQ)Q1: 我们公司已经用了主流 BI 工具，为什么还需要独立的指标平台？因为传统 BI 工具的指标定义是内置且绑定在该工具前端的，本质是增强工具粘性的功能模块。当企业存在多套BI工具，或需要向 AI 大模型、自建应用、WPS 表格插件等提供数据服务时，这些封闭的指标定义无法被复用。独立的指标平台作为中立的 Headless 基座，提供统一的标准 API，确保全企业“一次定义，处处使用”，口径 100% 一致。Q2: 统一指标平台和传统数据中台里的指标管理有什么区别？传统数据中台的指标管理多是“静态目录”，只记录指标元数据（如名称、口径描述），实际计算仍依赖底层人工开发、运维的物理宽表。而现代化的统一指标平台（如 Aloudata CAN）本身是一个动态计算引擎。它基于 NoETL 语义编织技术，直接在 DWD 明细层上通过声明式方式定义指标逻辑，并自动完成计算、物化加速与查询服务，实现了“定义即开发、定义即服务”。Q3: 实现指标统一，是不是意味着要推翻现有的数据仓库重来？完全不需要。推荐采用渐进式的 “三步走”资产演进法则：存量挂载：将现有逻辑成熟、性能稳定的物理宽表直接挂载到平台，快速统一查询出口。增量原生：所有新的分析需求，直接基于 DWD 明细层在平台上通过声明式定义敏捷响应，遏制宽表继续膨胀。存量替旧：逐步将维护成本高、逻辑变更频繁的旧宽表迁移至新的语义范式。这实现了平滑演进，而非颠覆式重建。Q4: 指标平台如何支持现在流行的 AI 智能问数（ChatBI）？混乱、非结构化的元数据是 AI 产生“幻觉”的根源。指标平台通过构建标准化的语义知识图谱（包含指标、维度、口径、血缘），为 AI 大模型提供了高质量的上下文。采用 NL2MQL2SQL 架构：用户自然语言提问 → LLM 生成基于语义知识的 MQL → 平台语义引擎将 MQL 翻译为精准、高效的 SQL → 智能路由至最优物化表或明细层执行 → 返回结果。这从根本上将 AI 生成 SQL 的“开放题”收敛为选择标准指标的“选择题”，实现高准确率。Q5: 对于数字化初期的企业，直接建设统一指标平台是不是“杀鸡用牛刀”？恰恰相反，这是实现 “数字化平权” 和弯道超车的战略机遇。传统企业经历了“先乱后治”的痛苦过程。数字化初期的企业可以直接采用最先进的“语义模型驱动”架构，跳过宽表泛滥、口径混乱的阶段，以较低门槛一步到位构建统一、敏捷、标准的数据服务能力，避免未来高昂的治理与重构成本。Key Takeaways（核心要点）指标混乱是“症”非“病”：它是传统烟囱式数据开发模式的必然产物，根源在于技术架构，而非管理能力。治理需解耦逻辑与物理：有效的指标治理必须将业务语义的定义，从物理宽表的开发中解放出来。统一语义层是核心：基于 NoETL 语义编织技术构建的统一指标平台，能够实现指标的“定义即开发、定义即服务”，成为企业唯一可信的数据事实源。价值超越降本增效：除了提升开发效率、降低资源成本，更能保障决策一致性、赋能业务敏捷分析，并构成未来 AI 应用不可或缺的 AI-Ready 数据底座。落地可渐进平滑：通过“存量挂载、增量原生、存量替旧”的三步走策略，企业可以在不影响现有业务的前提下，稳步向现代化数据架构演进。**查看更多技术干货与产品详情，请访问Aloudata 官方技术博客，查看原文：https://ai.noetl.cn/knowledge-base/why-companies-have-hundred...
不要再纠结 LLM 准确率了：从“回答对不对”到“系统是否值得信任”
生成式 AI 的投资回报远超预期？Snowflake 调研全球 1900 位企业与 IT 专业人士后发现平均 ROI 高达 41%！点击下载完整报告每个人都在努力提高大语言模型的精准度。但真正的挑战并非精度，而是上下文理解能力。在 BUILD 2025 大会上，Hex 合作伙伴工程负责人 Armin 探讨了为什么传统的方法，如评估套件或合成问题集往往不够有效，以及成功的 AI 系统是如何通过随着时间推移逐步积累上下文来构建的。由 Snowflake Cortex 提供支持的 Hex，启用了一个新的对话式分析模型，每次交互都让模型变得更聪明。通过 Hex 的 Notebook Agent 与 Threads 功能，业务用户可直接定义核心问题，而数据团队则将这些问题精炼、审计并转化为持久且值得信赖的工作流。在这个模型中，测试用例不再由数据团队闭门设计，而是由业务需求驱动并在数据工作流中自动实施，最终形成一个具有生命力的上下文系统，而非一成不变的提示词或测试集，它能随着组织共同演进。准确率不是终点Armin 开场就把矛头对准了一个常见做法：把业务用户会问的问题合成成一批样例，甚至进一步转成 SQL 查询，然后把这些喂给 LLM，用类似单元测试的方式去衡量它的准确率、稳定性与一致性。他不否认“准确性是顶层关注”，但他强调，把 LLM 当作传统软件组件来做单元测试，本身就是一个不合适的范式。原因在于，当你把业务问题硬转换为一组 SQL，并据此去构建样例与评估集时，你很难覆盖真实业务中不断变化的语义、不断扩张的问题空间，以及不同用户在不同语境下对同一指标的不同问法。更重要的是，即使你做出了一个看似通过率很高的测试集，也依然回答不了企业最在意的那件事：当它在真实环境中生成了一个结论，你如何知道它不是在胡编？你又如何知道它到底做了什么才得到这个结论？因此，Armin 把正确性从结果层拉回到系统层：你需要的不是一个靠样例证明自己正确的聊天机器人，而是一套可审计的系统，它能够随着时间变得灵活、可塑，能够让业务用户在使用中不断收敛可回答的问题类型，也能够让系统拥有被“硬化”的路径：哪些能力可以放开，哪些问题必须收紧，哪些定义需要固化，哪些数据应该进入上下文、哪些不应该。在他看来，真正有效的路线是：从一套能运行、能被观察的系统出发，让系统在使用中暴露问题、沉淀模式，再反过来加固上下文。这种思路听起来不如直接做评估来得爽快，但它更接近企业系统的真实生长方式。对话式分析如何变成“可审计的系统”为了把“可审计”讲得具体，Armin 用 Hex 的产品演示展示了对话式分析在真实系统中应该是什么形态。演示从一个非常典型的业务问题开始：假设我是营销经理，我想让系统分析销售机会的“首次触达来源”（first touch source），并做营销归因视角的拆解。这里一个很关键的动作，是他先在系统里配置模型提供方：通过密钥对（key pair）连接到 Snowflake 实例，使用 Snowflake Cortex 内托管的 Claude，并强调这是一个“walled garden”的私有网络环境。这样做的直接意义是：模型驻留在数据所在的环境里，数据可以传递给模型，同时也能让 IT 团队对数据出入边界更放心。进入线程后，Hex 并不是立刻吐出一句“结论”，而是在后台进行一系列用户不可见但决定可信度的步骤：它会先围绕可访问的元数据“思考”，查看平台上已有的 Hex 项目、仪表板或资产，判断是否存在可复用的内容；它会拉取来自数据仓库的表描述、列描述等元数据，并强调这些可以自动导入、不需要复杂配置；如果企业已经有 dbt 元数据，也可以进一步带入；随后它形成一个“漏斗式”的收敛过程：从广义元数据到相关表、再到更具体的模型信息与底层数据，最后才开始把 SQL 单元格、可能的 Python 单元格、图表与可视化逐步组织起来，用以回答最初的问题。这也解释了他在演示里专门强调的一个点：这种模式一开始会“慢”，但这是刻意设计的。因为此时系统面对的是生产数据仓库，它需要把大量上下文带进来，需要推理与迭代，而这类深度思考天然会以时间为代价。换来的收益是：它可以生成更细致、接近数据科学家或嵌入式数据分析师水平的分析过程。Armin 也提到，未来会有更偏“快速、短促回答”的迭代版本，可能更多依赖语义模型，而不是每次都在全量上下文里深挖。但在这个阶段，他们优先解决的是“在没有分析师介入的情况下，业务用户也能得到一份扎实的分析报告”。当线程生成结果后，界面里不仅有图表，还能继续做探索：拖拽维度与度量、查看底层表格数据、检查异常、做更深的切片。这时“可信度焦虑”就会自然出现：这么多信息暴露给业务用户，我怎么知道它没有幻觉？我该不该信这些 SQL？我如何让它更确定？Armin 的回答不是“相信模型”，而是把系统的底座亮出来：在 Hex 里，每一个线程、每一个项目，背后都由笔记本支撑。把线程保存为项目后，你可以在笔记本里看到完整对话以 Markdown 的形式呈现；更重要的是，你能看到它实际运行的 SQL、过滤条件、连接逻辑、图表生成过程，以及它如何一步步构建出整份报告。对于负责准确性与治理的数据团队来说，这种“把对话落到可审计的笔记本”非常关键——它让系统从一开始就具备被审核、被追责、被修正的可能。在此基础上，Armin 进一步展示了一个更现实的协作场景：业务用户提出问题后，不一定要立刻去找数据团队提工单，而是先在对话线程里得到初步洞察；如果需要更深入的分析（比如进一步做季节性拆解），技术用户可以把笔记本智能体（notebook agent）限定在这个项目范围内，和智能体一起继续规划、推理、生成图表，并在生成的“待处理变更”中逐条审核、决定保留哪些结果。分析由此变成一种可协作、可迭代、可沉淀的工作流，而不是一次性、不可解释的问答。从一次性对话到可复用资产如果到这里为止，Hex 展示的是“可观察性”，那么 Armin 在后半段想讲的，是上下文如何变成系统能力，如何从一次性对话沉淀为可复用资产。他先展示了一个从笔记本走向应用（app builder）的路径：当某些分析内容需要“持久化”，例如营销与销售负责人希望随时看到季节性分析或关键指标，而不是每次回来重新提问，那么就可以把笔记本中已经生成的图表、文本等资产拖拽到应用构建器里，做成一个仪表板、报告或更像 BI 的交互界面。这里的核心并不是“又做了一个 BI”，而是强调：即便呈现形态变成 BI 风格，背后依然由笔记本驱动，仍然保留 SQL、Python、Snowpark 等灵活性；同时，笔记本与应用这两种范式始终连接，资产是可回溯的。换句话说，展示层可以更友好，但底层逻辑并不会因此变成不可审计的黑箱。紧接着他抛出了“连接胶水”的问题：当我们有线程、有笔记本、有应用，如何让它们构成一个一致的策略？答案是语义模型——它是 Armin 所谓“上下文引擎”的关键组成部分。原因也很务实：企业里那些精心构建的报表与仪表板，通常包含大量转化逻辑、业务口径、SQL/Python 查询，这些恰恰是 LLM 最需要、也最容易误解的上下文。如果不能把这些上下文结构化，LLM 的确定性就无从谈起。在演示里，语义模型有两条路：一是导入已有的 Snowflake semantic view。Hex 可以浏览生产仓库、发现可访问的语义视图，然后快速引入，例如引入一个 B2B sales model，让 enriched metadata 直接在 Hex 中可用。另一条路更贴近多数团队的起点：不是先有语义视图，而是先有一堆被业务反复使用的仪表板项目。Hex 的语义建模工作台里有一个“建模智能体”（modeling agent），它能理解 Hex 的语义建模能力，并且能针对某个具体项目（例如 sales and marketing dashboard）去阅读项目里包含的 SQL 单元格、DataFrame 操作、joins、函数与过滤条件，形成建模计划，做错误预防，推断表关系，把“项目里已经存在的业务逻辑”烘焙进语义模型中。这一段其实回答了一个关键的企业问题：语义模型从哪来？它不一定需要从零凭空设计，它可以从企业已经在用的分析资产中被抽取、被规范、被版本化。建好之后，语义模型还能用一种“拖拽式”的方式被检查：你可以选择维度、度量，查看聚合、查看系统生成的 SQL，在发布之前把模型硬化到你满意的程度。更进一步，Armin 也回应了“供应商锁定”的担忧。他明确表示，Hex 不希望用专有 YAML 把用户锁死，并提到两个方向：其一是和 Snowflake 等一起推动“开放语义交换”（Open Semantic Interchange），一个由约 18 家甚至更多公司组成的联盟，目标是让语义模型信息能在不同系统之间互换，以促进 LLM 采用并避免 vendor lock-in；其二是更近期开启“写回”能力，让在 Hex 中构建的语义模型可以写回到 semantic views 中，保证不同系统间“友好共存”。这些内容在分享里出现得很明确：终点不是锁定格式，而是让用户愿意因为体验与工作流而持续使用。当语义模型准备好后，线程侧的使用方式也随之变化：你可以把对话线程限定为“只使用语义模型”，而不是访问整个生产数据仓库。Armin 强调，这会让系统随着时间更确定：当你不断硬化语义模型、补充上下文，它会越来越稳定、越来越可控。也正因此，他再次回到开场的观点：把精力放在构建上下文系统上，而不是试图用合成样例把原型聊天机器人测到“看起来准确”。规模化审计与上下文飞轮分享的最后一部分，Armin 把问题推到最现实的规模化挑战上：当系统从一个人试用扩展到五十、一百个用户时，你如何监控它？你如何知道 LLM 系统到底在做什么，业务用户到底拿它解决什么问题？这时，“可审计”就不能停留在某个线程或某个项目，而必须成为一套能覆盖全局的治理能力。他提到 Hex 的“上下文工作室”（context studio），目前处于少数 Alpha 合作伙伴的 Alpha 阶段，但他之所以专门强调它，是因为它承载了上下文系统最关键的一环：理解使用行为，反过来指导上下文如何演进。具体来说，你可以看到平台总体使用情况：用户更常用笔记本还是线程？创建了多少语义模型？也可以按对话量看用户分布，查看某个用户使用线程的频次、提问的类型。更重要的是，当你下钻到“问题类型”时，Armin 给出了一个很强的判断：这些真实问题才是你的单元测试。不是你在上线前试图一次性“破坏一切”并用评估集兜住，而是看清业务用户到底在问什么，再回去硬化你需要硬化的上下文与问题类型。围绕“如何策划上下文”，他在分享里给出了三个层次的抓手。最直接的是规则文件（rules file）：你可以在里面定义 SQL 的数据质量防护、业务定义、偏好的 SQL 风格、杂项信息，以及希望系统使用的可视化方式，并且这些内容可以即时编辑、保存或导出。第二层是“经认可的数据”（endorsed data）：由数据团队或所谓“金层”背书的数据资产，可以在 Hex 的语境下被定义清楚，决定哪些数据可以喂给 LLM。第三层则是更成熟、也最关键的做法：语义项目（semantic projects）。随着审计能力增强，你不仅能看到语义模型被使用的次数，还能观察是否有多个语义模型被同时使用、是否需要在某些场景中合并；你也能判断哪些项目最常被引用，从而决定是否需要对下游数据做更多建模，或者是否需要补充列描述、表描述等元数据来改善上下文质量。这些细节共同指向同一个结论：上下文不是一次性设计出来的，它是被真实使用不断“磨”出来的。你从稍微宽的范围起步，抽取一两个语义模型，让业务用户用起来；再通过审计看到真实问题与真实路径，回去修规则、补语义、加背书数据、完善元数据。如此循环，系统才会越来越确定、越来越可信。这场分享最有价值的地方，在于它没有把“可信”简化为一个指标，也没有把“准确率”当作唯一的归宿。Armin 反复强调的其实是另一套思维：企业要的不是一个在评估集上表现漂亮的聊天机器人，而是一套能持续吸收上下文、可审计、可治理的系统。从线程到笔记本的可观察性，从笔记本到应用的资产化，从项目到语义模型的上下文结构化，再到面向规模化使用的审计与上下文工作室——这些环节被串成一个整体，目的只有一个：让 LLM 在真实业务里变得更确定，并且在需求增长时仍然能保持可控与可信。原视频地址：https://www.snowflake.com/en/build/americas/agenda/?login=ML🔥【活动推荐】2 月 2 日-6 日，Snowflake Discover重磅上线！这是一场免费、线上、可实时互动的技术活动，旨在帮助您全面提升数据与 AI 能力，深入了解如何更高效地管理、整合与分析数据。4 天时间 18 场技术干货分享，由来自亚太地区的一线技术专家亲自分享与讲解～点击报名 Discover，更多 Snowflake 精彩活动请关注专区。
原文链接：https://www.nocobase.com/cn/blog/weekly-updates-20260129汇总一周产品更新日志，最新发布可以前往我们的博客查看。NocoBase 目前更新包括的版本更新包括三个分支：main ，next和 develop。main ：截止目前最稳定的版本，推荐安装此版本。next：包含即将发布的新功能，经过初步测试的版本，可能存在部分已知或未知问题。主要面向测试用户，用于收集反馈和进一步优化功能。适合愿意提前体验新功能并提供反馈的测试用户。develop：开发中的版本，包含最新的功能代码，可能尚未完成或存在较多不稳定因素，主要用于内部开发和快速迭代。适合对产品功能前沿发展感兴趣的技术用户，但可能存在较多问题或不完整功能，不建议在生产环境中使用。mainv1.9.40发布时间：2026-01-25🚀 优化[Office 文件预览] 支持更多文件类型在微软在线预览工具中预览 (#8500) by @mytharcher🐛 修复[client]修复 nanoid 字段在表单提交后不重新生成数据的问题 (#8491) by @katherinehhh修复级联组件必填校验重复提示的问题 (#8476) by @katherinehhh[database]修复数据表重载后使用 empty 操作符筛选报错的问题 (#8496) by @2013xile修复嵌套关联的深度更新问题 (#8492) by @chenos[文件管理器] 修复上传文件时请求中的文件名被重复解码产生的乱码问题 (#8481) by @mytharcher[数据源：主数据库] 修复在多对多关系表格区块中删除数据时，未遵循关系字段 onDelete: 'restrict' 约束的问题 (#8493) by @2013xile[区块：iframe] 修复 Iframe 添加聚合变量报错的问题 (#8482) by @zhangzhonghe[工作流：Webhook 触发器] 修复未配置请求体解析时触发器数据中该数据缺失的问题 by @mytharcher[模板打印] 复了联合角色时打印按钮权限逻辑错误 by @jiannx[工作流：审批]修复并发提交导致流程被重复恢复执行的问题 by @mytharcher修复分支模式的审批未能正确退回至指定节点的问题 by @mytharcher[迁移管理] 修复迁移异常后打印异常对象所包含 SQL 过大容易卡死进程的问题 by @cgyrocknextv2.0.0-beta.17发布时间：2026-01-29🐛 修复[client] 修复筛选相关的已知问题 (#8514) by @zhangzhonghe[AI 员工] 修复构建后系统无法启动问题 (#8523) by @cgyrock[AI: 知识库] 修复构建后系统无法启动问题 by @cgyrockv2.0.0-beta.16发布时间：2026-01-27🎉 新特性[client] 新增子表格（弹窗编辑）字段组件 (#8280) by @katherinehhh[工作流] 为移动节点增加 API (#8507) by @mytharcher🚀 优化[client]修复单元格更新导致表格整体重渲染 (#8349) by @katherinehhh改进对多子表单默认包含一个对象，无需点击 Add New，未填写时不创建记录 (#8458) by @katherinehhh[文件管理器] 为文件管理器增加可扩展的预览组件 (#8501) by @mytharcher[工作流] 修改工作流子页面的路由路径，将工作流页面都统一在 /admin/settings/workflow 路径之下 (#8519) by @mytharcher🐛 修复[client]修复筛选区块日期带时间时时间格式重复的问题 (#8506) by @zhangzhonghe修复多层级对多字段子表单字段联动规则无法使用表单变量赋值的问题。 (#8518) by @gchust修复多级弹窗及跨区块数据变更后不刷新问题。 (#8471) by @gchust修复编辑表单中配置阅读态子详情数据不能正常显示问题 (#8469) by @katherinehhh修复targetKey 可选字段的处理逻辑 (#8333) by @katherinehhh修复编辑态子表格中关系字段 Select 的 filter 参数错误问题 (#8335) by @katherinehhh[flow-engine] 修复外部数据源 filterTargetKey 为单元素数组时 FilterByTK 处理错误 (#8522) by @katherinehhh[AI 员工] 修复 AI 建模与数据源管理模块中可选字段配置不一致的问题 (#8488) by @cgyrock[邮件管理] 选中文本时正文不折叠。修复附件下载失败 by @jiannxv2.0.0-beta.15发布时间：2026-01-25🚀 优化[Office 文件预览] 支持更多文件类型在微软在线预览工具中预览 (#8500) by @mytharcher🐛 修复[database] 修复数据表重载后使用 empty 操作符筛选报错的问题 (#8496) by @2013xile[模板打印] 复了联合角色时打印按钮权限逻辑错误 by @jiannx[工作流：审批] 修复 1.x 审批记录弹窗报错的问题 by @mytharcher[迁移管理] 修复迁移异常后打印异常对象所包含sql过大容易卡死进程的问题 by @cgyrockv2.0.0-beta.14发布时间：2026-01-23🎉 新特性[AI 员工] AI 对话支持复制粘贴文件 (#8487) by @heziqiang🚀 优化[client]改进对多子表单默认包含一个对象，无需点击 Add New，未填写时不创建记录 (#8473) by @katherinehhh改进子表格中附件字段的上传与编辑按钮，引导用户点击上传 (#8474) by @katherinehhh[flow-engine] 优化 runjs 的 ctx.libs, 使其支持按需加载，并新增 lodash, math, formula 预定义库。 (#8468) by @gchust[错误处理器] 避免 SQL 引用错误直接暴露 (#8464) by @2013xile[工作流：审批] 增加对 API 的访问控制，以避免通过 API 越权操作数据 by @mytharcher🐛 修复[client]修复富文本编辑器的弹出层被遮挡的问题 (#8443) by @zhangzhonghe修复筛选区块日期带时间时时间格式重复的问题 (#8484) by @zhangzhonghe修复 nanoid 字段在表单提交后不重新生成数据的问题 (#8491) by @katherinehhh修复级联组件必填校验重复提示的问题 (#8476) by @katherinehhhfilter列表去重 (#8431) by @jiannx修复在 Chrome 144 版本中不显示配置菜单的问题 (#8470) by @zhangzhonghe[database]修复嵌套关联的深度更新问题 (#8492) by @chenos[server] 修复通用依赖中 mathjs 包的版本 (#8475) by @mytharcher[flow-engine] 修复内嵌弹窗页面连续打开联动规则配置和事件流配置后关闭弹窗报错的问题。 (#8368) by @gchust[数据源：主数据库] 修复在多对多关系表格区块中删除数据时，未遵循关系字段 onDelete: 'restrict' 约束的问题 (#8493) by @2013xile[异步任务管理器] 修复异步导入触发的工作流事件延迟执行的问题 (#8478) by @mytharcher[区块：iframe] 修复 Iframe 添加聚合变量报错的问题 (#8482) by @zhangzhonghe[UI 模板] 修复引用模板区块无法通过事件流设置数据范围的问题。 (#8472) by @gchust[文件管理器] 修复上传文件时请求中的文件名被重复解码产生的乱码问题 (#8481) by @mytharcher[操作：导入记录 Pro] 修复异步导入触发的工作流事件延迟执行的问题 by @mytharcher[工作流：Webhook 触发器] 修复未配置请求体解析时触发器数据中该数据缺失的问题 by @mytharcher[模板打印] 模板打印的配置模板弹窗移除底部按钮 by @katherinehhh[工作流：审批]修复分支模式的审批未能正确退回至指定节点的问题 by @mytharcher修复并发提交导致流程被重复恢复执行的问题 by @mytharcher修复审批任务卡片字段不显示的问题 by @zhangzhonghedevelopv2.0.0-alpha.68发布时间：2026-01-27🎉 新特性[工作流] 为移动节点增加 API (#8507) by @mytharcherv2.0.0-alpha.67发布时间：2026-01-26🎉 新特性[server] 重构应用监管器以适配不同场景下的多应用管理需求 (#8043) by @2013xile[client] 新增子表格（弹窗编辑）字段组件 (#8280) by @katherinehhh[AI 员工] AI 对话支持复制粘贴文件 (#8487) by @heziqiang🚀 优化[client]改进子表格中附件字段的上传与编辑按钮，引导用户点击上传 (#8474) by @katherinehhh改进对多子表单默认包含一个对象，无需点击 Add New，未填写时不创建记录 (#8473) by @katherinehhh[flow-engine] 优化 runjs 的 ctx.libs, 使其支持按需加载，并新增 lodash, math, formula 预定义库。 (#8468) by @gchust[server] 支持配置跨域 Origin 白名单 (#8454) by @2013xile[文件管理器] 为文件管理器增加可扩展的预览组件 (#8501) by @mytharcher[Office 文件预览] 支持更多文件类型在微软在线预览工具中预览 (#8500) by @mytharcher[错误处理器] 避免 SQL 引用错误直接暴露 (#8464) by @2013xile[操作：导出记录] 改进导出按钮数据范围：优先按选中记录，其次按前端筛选范围 (#8442) by @katherinehhh[操作：导出记录 Pro] 改进导出按钮数据范围：优先按选中记录，其次按前端筛选范围 by @katherinehhh[工作流：审批] 增加对 API 的访问控制，以避免通过 API 越权操作数据 by @mytharcher🐛 修复[client]修复筛选区块日期带时间时时间格式重复的问题 (#8484) by @zhangzhonghe修复 nanoid 字段在表单提交后不重新生成数据的问题 (#8491) by @katherinehhh修复富文本编辑器的弹出层被遮挡的问题 (#8443) by @zhangzhonghefilter列表去重 (#8431) by @jiannx修复级联组件必填校验重复提示的问题 (#8476) by @katherinehhh修复在 Chrome 144 版本中不显示配置菜单的问题 (#8470) by @zhangzhonghe修复编辑表单中配置阅读态子详情数据不能正常显示问题 (#8469) by @katherinehhh修复自定义变量弹窗被遮挡的问题 (#8463) by @zhangzhonghe修复数据表字段分组排序设置不生效问题 (#8453) by @katherinehhh修复表格“列设置”按钮无效的问题 (#8441) by @zhangzhonghe修复关系文件快速编辑，选择文件的弹窗层级错误，无法保存弹窗配置的问题。 (#8446) by @gchust修复数据表图形界面编辑数据表报错问题 (#8451) by @katherinehhh[database]修复数据表重载后使用 empty 操作符筛选报错的问题 (#8496) by @2013xile修复嵌套关联的深度更新问题 (#8492) by @chenos[server] 修复通用依赖中 mathjs 包的版本 (#8475) by @mytharcher[flow-engine]修复内嵌弹窗页面连续打开联动规则配置和事件流配置后关闭弹窗报错的问题。 (#8368) by @gchust修复能够重复点击配置菜单打开多个配置弹窗的问题。 (#8448) by @gchust修复 runjs 相关代码在运行前变量就被解析的问题。 (#8445) by @gchust修复数据选择器快速新增弹窗中无法选择弹窗变量的问题。 (#8450) by @gchust[AI 员工] 修复 AI 建模与数据源管理模块中可选字段配置不一致的问题 (#8488) by @cgyrock[数据源：主数据库] 修复在多对多关系表格区块中删除数据时，未遵循关系字段 onDelete: 'restrict' 约束的问题 (#8493) by @2013xile[区块：iframe] 修复 Iframe 添加聚合变量报错的问题 (#8482) by @zhangzhonghe[异步任务管理器] 修复异步导入触发的工作流事件延迟执行的问题 (#8478) by @mytharcher[文件管理器] 修复上传文件时请求中的文件名被重复解码产生的乱码问题 (#8481) by @mytharcher[UI 模板] 修复引用模板区块无法通过事件流设置数据范围的问题。 (#8472) by @gchust[移动端（已废弃）] 弃用移动端插件（2.0 后将使用 ui-layout 插件代替） (#8456) by @chenos[操作：导入记录 Pro] 修复异步导入触发的工作流事件延迟执行的问题 by @mytharcher[工作流：Webhook 触发器] 修复未配置请求体解析时触发器数据中该数据缺失的问题 by @mytharcher[模板打印]复了联合角色时打印按钮权限逻辑错误 by @jiannx模板打印的配置模板弹窗移除底部按钮 by @katherinehhh[工作流：审批]修复审批任务卡片字段不显示的问题 by @zhangzhonghe修复分支模式的审批未能正确退回至指定节点的问题 by @mytharcher修复并发提交导致流程被重复恢复执行的问题 by @mytharcher修复 1.x 审批记录弹窗报错的问题 by @mytharcher[邮件管理]修复邮箱配置弹窗被遮挡的问题 by @zhangzhonghe修复多个用户间相同邮箱邮件问题，性能优化 by @jiannx[迁移管理] 修复迁移异常后打印异常对象所包含 SQL 过大容易卡死进程的问题 by @cgyrock完全掌控，无限扩展，AI 协同。NocoBase 让你的团队快速响应变化，大幅降低成本。无需多年研发，无需数百万投入。花几分钟部署 NocoBase，立即拥有一切。访问 NocoBase 官网https://www.nocobase.com/cn您可以在官网申请 Demo 演示，体验站点将在 1 分钟内创建完毕自动发送到您的邮箱。访问 NocoBase GitHub 和 Giteehttps://github.com/nocobase/nocobasehttps://gitee.com/nocobase/nocobase下载 NocoBase 源码并安装。支持 Docker 安装、create-nocobase-app 安装和 Git 源码安装。官方文档持续更新中https://docs-cn.nocobase.com/
告别拼凑：记忆、检索与AI数据引擎的一站式技术栈解析（一）
作者：傅榕锋，OceanBase 高级技术专家AI 开发者需要什么样的数据库在开始正式话题前，我们不妨先思考一个问题： AI 时代下开发者需要什么样的数据库？自本世纪初以来数据库需求的演变历程。Web 2.0及业务在线化的时代，强调的是一个可靠、精确的记录系统，能够精准地记录每一笔交易数据，满足典型的事务处理（TP）需求。进入移动互联网和数据智能化时代后，随着数据量的爆发式增长，海量数据分析的需求成为主流。这时，分析型（AP）数据库开始占据重要位置。AI 时代的真正到来，驱动数据库不仅要支持查询和分析功能，更需具备理解和推理的能力。快来关注我，获取 OceanBase 第一手的产品信息和技术资源，与行业大咖 “唠” 出真知！AI 时代开发者的痛点作为数据库从业者，我们需要深入分析 AI 时代下开发者对数据库的具体需求。数据类型的多维化：在传统数据库中，图片、视频、音频仅能被存储而难以有效利用。借助 AI 模型的帮助，这些非结构化数据可以转化为可检索的形式，如通过嵌入模型转换为向量，或使用大语言模型提取文本描述和标签，从而将非结构化数据转变为结构化或半结构化数据以实现高效检索。性能与规模的极致化：鉴于向量数据对内存和磁盘资源的高占用特性，在成本与性能之间寻求最佳平衡显得尤为关键。为此，亟需采用高效的算法，以优化召回率与资源成本之间的权衡关系。智能处理的内生化：例如，在 RAG 场景中，文档需先进行切片并生成向量，这通常涉及向量数据库、文档型数据库以及事务型数据库的联合使用。为了简化这一流程，理想的解决方案是让数据库自身承担更多的标准化数据处理任务，减少开发者的负担。开发流程的敏捷化：目标是让开发者更加专注于业务逻辑本身，而非陷入复杂的数据处理流程之中。AI 时代的理想数据库基于上述痛点，AI 时代的理想数据库应具备以下四个特征。多模态支持：提供统一的平台，支持多种数据类型，包括但不限于向量、全文、标量、 JSON 格式。高性能引擎：针对 AI 工作负载进行优化，确保在控制成本的前提下实现最优性能表现。智能化集成：内置 AI 运行时环境，使数据库可以直接执行复杂的智能处理任务，减少对外部系统的依赖。简易操作：设计直观易用的界面和工具，降低非专业开发者的使用门槛，促进更多领域专家参与到数据处理工作中。综上所述， AI 时代我们期待的数据库应该是强大、智能、一体化的，是数据与 AI 融合的平台。AI原生的一体化数据库是否存在正所谓“需求决定市场”，契合AI时代理想数据库特质的产品必然会出现。而就目前来看，OceanBase 新发布的 seekdb 已率先落地，不仅具备了相关核心能力，更在快速迭代中持续进化。混搜架构的轻量级、多模态的AI原生数据库OceanBase seekdb 是一款面向 AI 场景的轻量级、多模态的原生数据库，专为支持混合搜索、上下文理解与智能数据处理而设计。其整体架构分为五个核心层级，实现从数据存储到查询执行的全链路优化。1. 统一应用接口层。seekdb提供基于 SQL 的统一查询语言，兼容标准 SQL 语法，支持多模态数据的联合查询。同时，提供面向开发者的 Python SDK，具备简洁易用的 API 接口，支持 skip-by-list 等高效检索模式，显著降低开发者使用门槛。2. 支持混合负载的多模计算层。继承自 OceanBase 的成熟优化器体系，seekdb具备强大的查询规划与执行能力，在混合检索场景中，会自动进行自适应执行和查询优化，能够根据查询条件自动选择最优执行路径。同时，支持混合负载自适应执行、AI 函数调用、ACID 事务保障及灵活 UDF 扩展，满足复杂业务需求。3. 多模数据层。支持多种数据类型统一存储，实现“存即能检”，打破传统系统中不同数据类型需分库管理的局限。包括：关系表（传统结构化数据）向量（Embedding 向量）文本（原始文本内容）JSON（半结构化数据）GIS（地理空间数据）数组、位图等扩展类型4. 多模索引层。构建业界领先的多模索引体系，支持的索引类型如下。向量索引：高效支持近邻搜索（ANN），兼顾精度与性能。全文索引：支持中文分词与语义匹配。混合索引：结合向量与标量条件进行联合检索。JSON 索引：加速嵌套字段查询。二级索引、GIS 索引：满足多样化查询需求。支持多索引协同查询，在一次请求中完成跨模态数据的融合检索。5. 部署模式层。服务器模式：传统集群部署，适用于高并发、大规模生产环境。嵌入式模式：以库的形式内嵌于应用程序中，生命周期与应用一致，适合边缘计算、AI 应用快速构建等轻量化场景。OceanBase seekdb 通过“统一接口 + 多模存储 + 智能索引 + 灵活部署”的一体化设计，实现了对 AI 工作负载的端到端支持，真正做到了“一个数据库，搞定所有数据”。快速构建：更灵活、更轻量、不止于 SQLOceanBase seekdb 不仅具备强大的功能，更在易用性和部署灵活性上进行了深度优化，助力开发者快速构建 AI 应用。1. 更灵活：双运行模式，适配多样场景。服务器模式：适用于企业级、高可用、分布式部署。嵌入式模式：直接集成到 #Python 应用中，无需独立部署数据库服务，极大简化开发流程，特别适合 RAG、Agent、智能问答等轻量级 AI 应用。2. 更轻量：极简资源占用，轻松跑起基准测试。单实例仅需 1C2G 内存即可运行 VectorDBBench 基准测试，相比传统数据库，资源消耗更低，启动更快，非常适合本地调试、原型验证和边缘部署。3. 不止于 SQL：引入 Schemaless SDK。引入 Schemaless SDK，开发者无需定义表结构即可直接插入和查询数据，提升开发灵活性。使用seekdb快速创建RAG应用下面我们演示一下如何使用 seekdb 快使创建一个 RAG 应用。第一步：三行代码快速创建一个知识库（SETUP）导入 pyseekdb 模块，启用 seekdb 的 Python SDK。初始化客户端实例，参数为空表示采用嵌入式模式，数据库生命周期与应用绑定，无需独立部署服务。创建知识库并定义为 Collection。第二步：批量插入文档片段（INSERT）功能说明：调用 upsert() 函数批量插入文档内容（documents）。同时关联元数据（metadatas），包括分类、内存、存储、价格等结构化信息。显式指定文档 ID（ids），便于后续检索与更新。关键特性：用户仅需提供原始文本和元数据，无需手动调用嵌入模型生成向量。数据库内部自动调用内置的嵌入模型，将文本转换为向量并存储。AI 能力下沉至数据库，开发者无需关注向量化过程，seekdb 自动完成文本 → 向量的转换，实现“透明化”处理。第三步：混合检索，精准召回（QUERY）查询维度分析：query_texts：输入自然语言文本，触发向量检索，用于语义匹配。where：设置关系型过滤条件，如 category == laptop 和 ram >= 16，实现精确筛选。where_document：基于全文索引进行关键词匹配，要求文档内容包含 “RAM”。n_results：限制返回结果数量为 2 条。实现机制：查询时，seekdb 内部自动将 query_texts 输入传递给嵌入模型，生成查询向量。结合向量索引、全文索引、二级索引等多种索引执行混合检索。最终返回满足所有条件的最相关结果。第四步：效果展示输入检索条件为：需要一个 12 GB 内存以上的高性能笔记本。运行后输出结果如下图所示，召回结果分析如下。第一条：16GB 内存、512GB 固态的专业笔记本，完全满足“高性能 + 16GB 以上内存”的要求。第二条：32GB 内存、1TB 固态的游戏本，虽非专业用途但性能卓越，符合语义意图。该案例模拟了典型的 RAG 场景，用户只需输入自然语言问题，系统即可自动完成文本向量化、多条件联合检索、高精度召回。全流程由数据库内核统一处理，极大简化了开发复杂度,真正实现“让开发者专注于业务，而非数据处理”。欢迎亲自上手试用：https://github.com/oceanbase/seekdb。当前版本支持 Linux 平台下的嵌入式模式运行，Windows 和 macOS 版本将在近期和大家见面。可访问 oceanbase.ai 获取样例代码，支持本地测试与快速验证。SQL 直接调用 AI 的原生体验OceanBase seekdb 不仅是一个支持多模态数据存储与混合检索的数据库，更致力于将 AI 能力深度集成于数据库内核，实现“SQL 直接调用 AI”的原生体验。seekdb AI Inside 的内置处理除了 AI_EMBED 方法外，还引入 AI_RERANK 和 AI_COMPLETE，可以实现数据分析自动化、特征提取、智能内容生成、语义搜索增强、结果优化等效果。在 seekdb 中使用可以构建从粗排到精排的高效分层混合检索处理流程。该流程分为四个阶段。阶段1：标量过滤（Scalar Filtering）。在全量数据集上首先执行关系型条件过滤（如 category = 'laptop', ram >= 16），缩小候选集过滤范围。阶段2：向量搜索（Vector Search）。对过滤后的候选集执行向量相似度检索，基于语义匹配找出最相关的文档，使用近邻搜索算法（ANN）高效完成高维向量比对。阶段3：全文搜索（Full-text Search）。在候选集中进一步执行关键词匹配，确保结果包含用户关心的关键信息（如 "RAM"），支持中文分词与模糊匹配，提升召回精度。其中标量、向量、全文的过滤顺序取决于优化器。阶段4：粗排 → 精排 → 大模型重排。经过以上过滤后得到粗排的结果，此时再去调用 AI_RERANK，数据库会直接调用 RERANK 模型进行精排，精排结束后，通过调用 AI_COMPLETE 即可调用大模型，大模型会直接进行回答。以上所有的 AI 标准操作流程都在数据库中进行，开发者只需在查询中添加相应函数，即可让数据库自动调用大模型对数据进行处理，显著提升用户体验。OceanBase seekdb 适用场景OceanBase seekdb 作为一款轻量级、多模态、AI 原生的数据库，凭借其统一存储、混合检索、内嵌 AI 能力 和嵌入式部署支持，在多个新兴与传统智能化场景中展现出显著优势。以下是其典型的适用场景。1.替代“三库并行”，降本增效在 RAG 架构中，传统方案通常需要同时维护三类数据库。向量数据库存储文本嵌入向量。文档数据库保存原始文本内容。关系型数据库管理元数据（如分类、时间、权限等）。这种“三库并行”模式不仅带来高昂的运维复杂度，还导致资源重复占用（三份独立实例），难以在资源受限的本地或边缘环境中落地。seekdb 通过单一数据库统一承载向量、文本与结构化元数据，实现一次写入，多路索引（向量索引 + 全文索引 + 二级索引）、统一查询接口，支持混合条件过滤、极低资源开销（1C2G 即可运行），适合个人本地知识库、中小企业内部知识管理系统、边缘侧智能问答应用等。2.语义搜索引擎，打破模态壁垒seekdb 的多模态能力使其天然适配跨模态语义搜索场景。无论是文本、图片、音频还是视频，均可通过嵌入模型转化为统一的向量表示，并结合元数据进行联合检索，通过统一向量 + 元数据 + 全文的混合检索框架，打破模态壁垒。典型应用包括：以图搜图、音频内容检、视频片段语义匹配、多媒体资产管理系统。3.Agentic AI 应用，保证数据一致性在 Agentic AI（智能体）场景中，Agent 需要频繁执行上下文感知的混合检索，比如结合用户历史行为（标量过滤）、匹配任务目标语义（向量搜索）、检索相关文档片段（全文匹配）。seekdb 的原生混合检索引擎与内嵌 AI 函数能够高效支撑此类复杂查询，避免外部服务调用带来的延迟与一致性问题。适用于任务型对话系统、自主决策机器人、智能工作流引擎等应用场景。4.AI 辅助编程，提升质量，降低成本AI 编程助手存在云端 + 客户端双端检索需求，传统方案面临两大挑战。架构割裂：云端使用多源召回（向量+全文+语法树），客户端依赖轻量插件（如 SQLite + 向量扩展），两套系统逻辑不一致。性能瓶颈：通用数据库缺乏专业向量索引与优化器，召回效果与效率受限。seekdb 提供统一的 SDK 与查询接口，可使云端与客户端使用同一套 API，且客户端在嵌入式模式下仍具备专业级向量检索能力。seekdb还支持代码语义搜索、API 推荐、错误修复建议等高级功能。通过这些能力统一技术栈，提升召回质量，降低双端开发与维护成本。5.企业应用智能化丝滑升级对于大量仍在使用 MySQL 的传统企业应用，seekdb 提供了一条平滑演进路径：高度兼容 MySQL 协议，现有应用可无缝迁移。迁移后即可获得 向量检索、全文搜索、JSON 支持等 AI 原生能力。为未来引入 RAG、智能报表、自动化分析等 AI 功能奠定数据基础。因此，MySQL 到 OceanBase 的迁移是“最丝滑”的路径之一。seekdb 作为其轻量化延伸，进一步降低了企业智能化转型的技术门槛。6.端侧应用智能化的理想选择随着终端设备算力提升，越来越多智能应用向端侧迁移。seekdb 的嵌入式部署能力使其成为端侧智能数据库的理想选择：资源占用极低（1C2G 可运行）。支持离线向量检索与语义理解。生命周期与应用绑定，无需独立服务进程。让端侧应用具备“本地大脑”，减少对云服务的依赖。典型场景包括：智能家居设备中的本地知识问答。工业机器人中的实时故障诊断。移动端个人助理的上下文记忆管理。车载系统的本地语义导航。从轻到重、从简到繁： AI 应用快速迭代的理想基础设施在 AI 应用快速迭代的背景下，开发者面临从原型验证、开发测试到生产部署的多阶段需求。OceanBase 与 seekdb 的深度融合，构建了一套覆盖全生命周期、支持平滑演进的弹性数据库架构，能够满足不同阶段、不同规模场景下的灵活部署需求。原型验证与开发测试阶段：嵌入式模式（seekdb）在项目初期，开发者通常需要快速验证 AI 模型效果或构建最小可行产品（MVP）。此时可采用 seekdb 嵌入式模式：将 libseekdb.so 动态库直接集成至应用中，作为本地数据库运行。数据库生命周期与应用绑定，启动即用，关闭即销毁。无需独立部署服务，极大简化环境搭建流程。支持向量、文本、JSON 等多模态数据存储与混合检索。嵌入式模式适用于个人开发者快速原型开发、端侧智能应用（如移动端、机器人）、本地调试与算法验证等场景。测试与小规模生产环境：单机部署模式当应用进入测试或小规模上线阶段，可迁移到单机部署模式：启动独立的 seekdb 进程，提供服务端接口。支持多客户端连接，适合团队协作开发。可通过配置文件管理数据路径、内存参数等。仍保持与嵌入式模式的 API 兼容性，代码无需变更。单机部署模式适用于小型工作负载、测试环境与生产环境、多租户需求等场景。生产环境：多租户与高可用架构随着业务稳定运行，需考虑资源隔离、高可用性和容灾能力，此时可选择以下两种生产级部署方式。单机多租户模式（OceanBase 单机部署） ：使用 OceanBase 单机实例，通过多租户机制实现多个业务之间的资源隔离。适用于多个业务共享同一数据库实例但需独立管理资源的场景。支持独立的配额控制、备份策略和监控告警。主备模式 / 三副本模式（OceanBase 高可用架构）：采用主备架构或三副本（2F1A）架构，保障数据高可用。支持自动故障切换与读写分离。适用于对稳定性要求较高的中小规模业务系统。多租户与高可用架构适用于中小规模工作负载、对容灾和高可用有明确要求的业务、多租户共用数据库的 SaaS 平台等场景。大规模与高性能场景：分布式集群架构当业务持续增长，数据量和并发请求激增时，可进一步扩展为分布式集群架构。无共享分布式集群 ：由多个 OBServer 节点组成，支持水平扩展。支持大规模工作负载、关键业务高并发访问。具备强一致性、线性可扩展性与动态扩容能力。基于对象存储的存算分离集群：存储层使用对象存储（如 OSS），计算层由 OBServer 提供。实现“冷热数据分离”，降低存储成本。适用于海量非敏感数据分析场景（如日志分析、历史归档）。提供更高的性价比与更强的扩展能力。分布式集群架构适用于大规模工作负载、关键业务系统、高性能高并发、更高性价比的大数据处理任务等场景。OceanBase 与 seekdb 的组合形成了一个 “从轻到重、从简到繁” 的完整弹性架构体系，核心优势有如下三点。API 完全兼容：无论选择哪种部署模式，业务代码无需修改；配置驱动升级：只需更改连接地址与配置参数，即可完成架构迁移；平滑演进路径：支持从个人开发到企业级生产的无缝过渡。这使得 OceanBase + seekdb 成为 AI 应用快速迭代的理想基础设施，真正实现了“一次开发，全栈适配”，助力企业在 AI 时代加速创新落地。当然，在AI时代，AI数据库不足以支撑应用所需的完整基础设施能力，因此，OceanBase构建了上下文工程体系中的关键能力。让我们敬请期待下一篇文章。
MyBatis Dynamic SQL 是一种类型安全的 Java 领域特定语言（DSL），用于通过编程方式构建 SQL 查询，而非编写 SQL 字符串或基于 XML 的动态查询。它在运行时使用流畅的 Java 构建器生成 SQL，同时仍通过标准的 MyBatis 映射器执行。与手动拼接字符串或复杂的 XML 逻辑相比，这使得查询构建更安全、更易于重构，并且更不容易出错。由于查询是用 Java 编写的，列名和表引用通过强类型的元数据类在编译时进行验证，这提供了更好的 IDE 支持并减少了运行时 SQL 错误。本文将解释 MyBatis Dynamic SQL，并展示如何在 Java 应用程序中使用它。1. 使用 MyBatis Dynamic SQL 可以做什么？MyBatis Dynamic SQL 支持大多数常见的 SQL 操作，包括 SELECT、INSERT、UPDATE 和 DELETE，以及连接、子查询、分页、排序、条件过滤和批量操作。它允许我们逐步构建查询，仅在某些参数存在时添加条件，这使其成为搜索界面和过滤 API 的理想选择。它直接与 MyBatis 映射器接口集成，意味着我们仍然可以受益于结果映射、事务处理和连接管理。由于它生成标准的 SQL，因此适用于 MyBatis 支持的任何数据库，没有供应商锁定的问题。1.1 MyBatis Dynamic SQL 的工作原理Dynamic SQL 基于两个组件：表元数据类和 DSL 构建器。元数据类用 Java 描述表和列。DSL 构建器使用这些类以流畅、类型安全的方式组装 SQL 语句。DSL 不直接执行 SQL。相反，它生成语句提供者对象，例如 SelectStatementProvider 或 InsertStatementProvider。这些对象被传递给使用 @SelectProvider、@InsertProvider 及类似注解标注的映射器方法，然后 MyBatis 使用其正常的执行引擎来执行这些语句。2. 项目设置与依赖Maven 依赖<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.15</version> </dependency> <dependency> <groupId>org.mybatis.dynamic-sql</groupId> <artifactId>mybatis-dynamic-sql</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>2.4.240</version> <scope>runtime</scope> </dependency>这些依赖项包括 MyBatis 本身、Dynamic SQL DSL 以及一个用于测试的嵌入式数据库。注意数据库驱动可以替换为 MySQL、PostgreSQL 或任何其他支持的数据库。MyBatis Dynamic SQL 不依赖于数据库类型，仅依赖于标准 SQL 生成。数据库模式schema.sqlCREATE TABLE users ( id BIGINT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL, email VARCHAR(100), age INT ); INSERT INTO users(username, email, age) VALUES ('thomas', 'thomas@jcg.com', 30), ('benjamin', 'benjamin@jcg.com', 22), ('charles', 'charles@jcg.com', 17);此脚本创建一个简单的表并插入测试数据。内存中的 H2 数据库将在启动时执行此脚本，因此无需外部依赖即可测试查询。领域模型public class User { private Long id; private String username; private String email; private Integer age; // Getter 和 Setter 方法... }这个 POJO 代表数据库中的一行。MyBatis 会自动使用匹配的字段名将列映射到字段，因此本例不需要额外的结果映射。3. 用于 Dynamic SQL 的表元数据下面的类以类型安全的方式定义数据库表及其列，允许在构建查询时被 Dynamic SQL DSL 引用。它充当 Java 代码与实际数据库结构之间的桥梁，实现了列名和类型的编译时验证。public final class UserDynamicSqlSupport { public static final User user = new User(); public static final SqlColumn<Long> id = user.id; public static final SqlColumn<String> username = user.username; public static final SqlColumn<String> email = user.email; public static final SqlColumn<Integer> age = user.age; public static final class User extends SqlTable { public final SqlColumn<Long> id = column("id", JDBCType.BIGINT); public final SqlColumn<String> username = column("username", JDBCType.VARCHAR); public final SqlColumn<String> email = column("email", JDBCType.VARCHAR); public final SqlColumn<Integer> age = column("age", JDBCType.INTEGER); public User() { super("users"); } } }这个类为 users 表定义了类型安全的元数据，使 MyBatis Dynamic SQL 可以在不使用原始 SQL 字符串的情况下构建查询。DSL 使用这些 Java 对象而非按名称引用列，从而提高了安全性和 IDE 支持。内部类 User 继承 SqlTable，这将其标记为可用于 from(user) 和连接等子句的数据表。构造函数调用 super("users") 来告知 MyBatis 要在 SQL 语句（如 FROM users）中呈现的确切表名。每个列都使用 SqlTable 中的 column() 方法定义，该方法注册列名及其 JDBC 类型。这会产生强类型的 SqlColumn<T> 对象，确保比较和条件在编译时使用正确的 Java 类型。外部类公开了对表及其列的静态引用，以便于静态导入，使得查询读起来很自然，例如：select(id, username).from(user)，同时保持完全的类型安全和重构友好。映射器接口@Mapper public interface UserMapper { @SelectProvider(type = SqlProviderAdapter.class, method = "select") List<User> selectMany(SelectStatementProvider selectStatement); }@Mapper 注解告诉 MyBatis 此接口应注册为映射器并在运行时进行代理。MyBatis 会自动生成实现，因此不需要具体的类。selectMany 方法接受一个 SelectStatementProvider，它封装了完全呈现的 SQL 语句及其参数。MyBatis 执行该语句并将每个结果行映射到 User 对象，将它们作为 List<User> 返回。@SelectProvider 注解指定 SQL 将由 MyBatis Dynamic SQL 的一部分 SqlProviderAdapter 动态提供。实际的 SQL 是在运行时从使用 DSL 构建的 SelectStatementProvider 生成的，而不是在注解或 XML 中编写 SQL。4. 构建动态查询在这里，我们使用流畅的 Dynamic SQL DSL 构建 SQL 语句，而不是编写原始 SQL 字符串。public static void main(String[] args) throws Exception { MyBatisUtil.runSchema(); try (SqlSession session = MyBatisUtil.getSession()) { UserMapper mapper = session.getMapper(UserMapper.class); SelectStatementProvider select = select(id, username, email, age) .from(user) .where(age, isGreaterThan(18)) .and(username, isLike("%tho%")) .orderBy(username) .build() .render(RenderingStrategies.MYBATIS3); List<User> users = mapper.selectMany(select); users.forEach(u -> System.out.println(u.getUsername() + " - " + u.getAge())); } }此代码使用流畅的 Dynamic SQL DSL 动态构建一个 SELECT 查询，并将其渲染为与 MyBatis 兼容的语句提供者。通过以编程方式添加条件，它能够以类型安全且可维护的方式创建复杂的过滤器。在本例中，查询选择 age 大于 18 岁且 username 包含 "tho" 的用户，然后按用户名字母顺序对结果进行排序。MyBatis 工具类public class MyBatisUtil { private static SqlSessionFactory factory; static { try { Reader reader = Resources.getResourceAsReader("mybatis-config.xml"); factory = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { throw new RuntimeException(e); } } public static SqlSession getSession() { return factory.openSession(true); } public static void runSchema() throws IOException, SQLException { try (SqlSession session = getSession()) { Connection conn = session.getConnection(); Statement stmt = conn.createStatement(); try (InputStream is = Resources.getResourceAsStream("schema.sql")) { String sql = new String(is.readAllBytes(), StandardCharsets.UTF_8); stmt.execute(sql); } } } }此工具类加载 MyBatis 配置，构建 SqlSessionFactory，并提供对数据库会话的访问。它还通过执行 SQL 脚本（schema.sql）手动初始化数据库模式。5. 使用 Dynamic SQL 进行插入、更新和删除MyBatis 中的 Dynamic SQL 允许我们使用流畅的 DSL 以编程方式构造 INSERT、UPDATE 和 DELETE 语句。在此，我们演示如何执行这些常见的数据操作。// INSERT User newUser = new User(); newUser.setUsername("andrew"); newUser.setEmail("andrew@jcg.com"); newUser.setAge(28); InsertStatementProvider<User> insert = insert(newUser) .into(user) .map(username).toProperty("username") .map(email).toProperty("email") .map(age).toProperty("age") .build() .render(RenderingStrategies.MYBATIS3); int inserted = mapper.insert(insert); System.out.println("Rows inserted: " + inserted); // UPDATE UpdateStatementProvider update = update(user) .set(age).equalTo(35) .where(username, isEqualTo("thomas")) .build() .render(RenderingStrategies.MYBATIS3); int updated = mapper.update(update); System.out.println("Rows updated: " + updated); // DELETE DeleteStatementProvider delete = deleteFrom(user) .where(age, isLessThan(18)) .build() .render(RenderingStrategies.MYBATIS3); int deleted = mapper.delete(delete); System.out.println("Rows deleted: " + deleted);相同的 DSL 风格也用于写操作。语句以流畅的方式构建、渲染，然后由映射器提供者方法执行。INSERT：创建一个新的 User 对象并填充值。使用 Dynamic SQL DSL，我们将其字段映射到表列并生成 InsertStatementProvider。映射器执行插入操作，返回受影响的行数。UPDATE：DSL 构建一个更新语句，将用户名为 "thomas" 的用户的年龄设置为 35。这确保只修改目标行，映射器执行更新。DELETE：删除语句移除所有年龄小于 18 岁的用户。在 DSL 中使用条件保证了类型安全并避免了字符串拼接。更新后的映射器接口为了支持这些操作，映射器接口必须包含用于 INSERT、UPDATE 和 DELETE 的方法，使用 MyBatis Dynamic SQL 提供者。// INSERT @InsertProvider(type = SqlProviderAdapter.class, method = "insert") int insert(InsertStatementProvider<User> insertStatement); // UPDATE @UpdateProvider(type = SqlProviderAdapter.class, method = "update") int update(UpdateStatementProvider updateStatement); // DELETE @DeleteProvider(type = SqlProviderAdapter.class, method = "delete") int delete(DeleteStatementProvider deleteStatement);映射器中的每个方法处理一个特定的 DML 操作（插入、更新或删除），并接受一个封装了生成的 SQL 及其参数的 InsertStatementProvider、UpdateStatementProvider 或 DeleteStatementProvider。这种方法允许所有写操作都在 Java 中以编程方式表达，而无需手动组合 SQL 字符串，同时仍能利用 MyBatis 高效地执行语句和映射结果。6. 结论在本文中，我们探讨了如何在 Java 应用程序中使用 MyBatis Dynamic SQL 来创建类型安全、可维护且可编程的 SQL 查询。通过将 SQL 构建与执行分离，MyBatis Dynamic SQL 简化了复杂查询逻辑的处理，降低了错误风险，并提高了代码可读性。这种方法非常适合查询需要动态变化或经常修改的应用程序。7. 下载源代码本文讨论了 MyBatis Dynamic SQL 及其在 Java 中的使用方法。下载您可以通过此处下载此示例的完整源代码：java mybatis dynamic sql【注】本文译自：Getting Started with MyBatis Dynamic SQL