别只盯着慢 SQL:一次 product_profile 超大 IN 背后的报表任务排查

简介: 一次 SaaS ERP 报表慢 SQL 排查复盘:从一条 product_profile 超大 IN 查询开始,先还原服务器时间、商户本地时区和报表任务窗口,再追到商品日报、库存日报共用商品资料加载链路,最后对比 IN 分批、列裁剪、按需加载、改 Cron 和缓存等方案。文章重点不是单条 SQL 写法,而是报表任务输入规模、业务口径、调度窗口和验证回归的整体治理。

报表大 IN 优化:一条 product_profile 超大 IN SQL 背后的报表任务治理

0. 先说结论

有些慢 SQL 看起来只是数据库问题:

SELECT *
FROM product_profile
WHERE deleted = 0
  AND merchant_id = ?
  AND id IN (?, ?, ?, ...);

IN 里面几百、几千个商品资料 ID,SQL 文本很长,字段还全量返回。

直觉上的优化方案很容易落到这几类:

给 id 加索引。
把 IN 拆小。
调整慢 SQL 阈值。
改定时任务时间。
加缓存。

这些都可能有用,但如果只盯着一条 SQL,很容易治标不治本。

这次排查真正有价值的地方,不是发现了某个参数,而是把“报表任务”拆开看清楚了:

慢 SQL 出现在哪个时间窗口?
这个时间是系统时区,还是商户本地时区?
哪几个报表任务连续触发?
为什么单商户会把历史全部 SKU 塞进一条 IN?
未售商品到底要不要进报表?
优化要先保口径,还是直接改查询范围?

我最后更认可的治理路径是:

第一层:先做 IN 分批,控制单条 SQL 体积,保持报表口径不变。
第二层:再做列裁剪,减少无意义 IO。
第三层:和产品确认报表口径后,改成按需加载商品资料。
第四层:把报表任务的时区、调度窗口、重算范围和观测指标纳入治理。

这篇文章聊一次报表大 IN 排查:从一条 product_profile 超大 IN SQL 开始,怎么通过时间还原、调用链追踪、方案对比和任务治理,把它从“SQL 优化问题”升级成“报表生成链路治理问题”。

1. 现象:一条看起来不太对劲的 SQL

监控里看到的 SQL 形态大概是这样:

SELECT id,
       merchant_id,
       product_group_id,
       type,
       combo_mode,
       major_name,
       minor_name,
       product_code,
       remark,
       ...
FROM product_profile
WHERE deleted = 0
  AND merchant_id = ?
  AND id IN (?, ?, ?, ...);

特征很明显:

特征 说明
单商户 merchant_id 只有一个商户
超大 IN id IN (...) 里塞了大量商品资料 ID
全字段 查询没有列裁剪,等价于把商品资料整行拉出
定时出现 集中出现在每天凌晨附近的报表窗口
重复出现 库存类报表和商品类报表相隔不久连续命中

这个时候先不要急着问“为什么 MySQL 没走好索引”。

因为 merchant_id + id 本身通常已经具备较强过滤能力。问题的核心不是单个 ID 查不到,而是系统把太多 ID 放进同一条 SQL 里,同时还返回了不必要的列。

这类 SQL 的风险不只在执行耗时。

它还会带来:

SQL 文本过长。
数据库解析成本上升。
网络传输变大。
连接持有时间变长。
报表 Job 被拖慢。
同一时间窗口的其他任务被挤压。

如果商户商品量继续增长,原本只是“偶发慢查询”的问题,后面很容易变成“定时任务窗口不稳定”。

2. 第一步不是改 SQL,而是还原时间

排查定时任务问题时,时间非常容易误导人。

比如日志里看到北京时间早上 06:30 附近出现大量报表 SQL,第一反应可能是:

为什么早上 6 点多跑报表?
是不是定时任务配置错了?
是不是所有商户都挤在北京时间触发?

但如果系统是海外 SaaS,多租户又按商户本地时区跑任务,这个判断就不一定成立。

假设某个商户在 UTC+3 时区:

北京时间 06:15 = 商户本地 01:15
北京时间 06:30 = 商户本地 01:30

也就是说,监控里看到的“北京时间早上 06:30”,实际可能是商户当地的凌晨报表窗口。

这一步很关键,因为它把问题从“系统为什么早上跑任务”,变成了:

商户本地凌晨有哪些报表任务会连续触发?
这些任务是不是共享同一条商品资料加载链路?
调度间隔是否足够?
慢 SQL 是否集中在同一个任务窗口?

我一般会先画一个时间对照表。

平台观测时间 商户本地时间 任务类型 排查判断
06:15 01:15 库存日报类任务 可能触发商品资料加载
06:30 01:30 商品日报类任务 可能再次触发同类加载
06:45 01:45 财务日报类任务 需确认是否经过商品链路
07:15 02:15 业绩类任务 需确认是否与本 SQL 相关

report-large-in-timezone.png

这里有一个经验:定时任务排查不要只看“服务器时间”。必须把服务器时间、平台观测时间、商户本地时间和业务日边界放在同一张表里。

否则你可能会把一个正常的商户本地凌晨任务,看成异常的北京时间任务。

3. 调用链:为什么单商户会拼出超大 IN

时间窗口确认后,下一步是追调用链。

抽象后的链路大概是这样:

报表调度器
-> 商品日报生成
-> 加载报表日期截止前的商品 SKU
-> 收集这些 SKU 所属的商品资料 ID
-> 查询 product_profile
-> 回填商品名称、分类、编码等展示字段
-> 生成日报行

问题出在“加载商品资料”的边界上。

报表任务真正需要的是当天报表要展示的商品维度信息。

但旧链路为了兼容“全量商品日报”或“已删商品补齐”等逻辑,可能会把某个商户历史截止到报表日的全部 SKU 拉出来,再收集它们对应的全部 product_profile ID,一次性去查商品资料表。

这就解释了为什么 SQL 是单商户超大 IN:

Job 外层已经按商户分批。
每批只处理一个商户。
但商户内部又把历史全部商品资料 ID 一次性查出。

于是数据库看到的不是“多个商户各查一点”,而是:

某一个大商品量商户,一条 SQL 查几百到几千个 product_profile。

如果餐饮、零售、组合商品、修饰符、套餐子项都共用商品资料体系,商品数量增长会更快。大商户不一定订单多,但只要商品资料历史积累多,报表任务就会把这个问题放大。

report-large-in-call-chain.png

4. 根因不是 IN,而是“报表维度加载没有边界”

很多人看到大 IN 后,会直接把结论写成:

IN 太大,拆分即可。

这个结论只对了一半。

IN 太大是表象,更深一层的问题是:报表维度加载没有边界。

它混在一起处理了三件事:

当天有销售事实的商品。
历史上存在但当天没有销售的商品。
订单里出现过但商品资料可能已删除或隐藏的商品。

这三类商品的报表语义完全不同。

类型 是否一定要查 说明
有销售或退单事实的商品 是 报表事实必须展示
已删除但历史订单用过的商品 是 需要历史回显和差异补齐
没有任何业务事实的未售商品 不一定 取决于产品口径

如果产品口径要求“商品日报只展示有销售或退单事实的商品”,那报表根本不应该加载商户历史全部商品。

如果产品口径要求“即使未售商品也要生成 0 行”,那可以保留全量加载,但必须承认这是一种业务口径成本:商品越多,报表任务越重。

所以这个问题不能只在技术层面拍脑袋。它需要先分成两个层级:

技术治理:不改变口径,先把单条 SQL 风险降下来。
业务治理:确认报表展示口径,再决定是否减少加载范围。

5. 为什么不建议第一步就改成按需查询

从工程直觉看,最优雅的方案似乎是:

只查当天订单涉及的商品。
不查未售商品。

但我不建议第一步就这么改。

原因是它会改变报表口径。

比如旧报表可能有一个隐含行为:每天为所有商品生成日报行,即使当天销量为 0。这个行为技术上很重,但它可能已经被某些客户、导出模板或历史对账流程依赖。

如果没有确认就直接按需查询,慢 SQL 可能消失了,但客户看到的报表行数也变了。

这类优化最危险的地方,不是代码改错,而是把“性能优化”做成了“业务口径变更”。

所以更稳的拆法是:

Phase 0:IN 分批,保持口径不变。
Phase 1:列裁剪,保持口径不变。
Phase 2:产品确认后,报表按需加载商品资料。
Phase 3:重算、灰度、观测和任务窗口治理。

先把生产风险压住,再谈更彻底的模型优化。

6. 方案一:IN 分批,控制单条 SQL 体积

最小风险方案是给商品资料批量查询加分批。

伪代码大概是这样:

public Map<Long, ProductProfile> listProfileMap(Long merchantId, Collection<Long> profileIds) {
   
    if (profileIds == null || profileIds.isEmpty()) {
   
        return Collections.emptyMap();
    }

    List<Long> distinctIds = profileIds.stream()
        .filter(Objects::nonNull)
        .distinct()
        .collect(Collectors.toList());

    if (distinctIds.size() > 500) {
   
        log.warn("Large product profile query partitioned, idCount={}", distinctIds.size());
    }

    Map<Long, ProductProfile> result = new LinkedHashMap<>();
    for (List<Long> batch : partition(distinctIds, 500)) {
   
        List<ProductProfile> profileList = repository.listByMerchantAndIds(merchantId, batch);
        for (ProductProfile item : profileList) {
   
            result.putIfAbsent(item.getId(), item);
        }
    }
    return result;
}

这里的重点不是 500 这个数字本身,而是要有一个上限。

没有上限时,调用方传 50 个 ID 和 5000 个 ID,对底层查询方法来说是一样的。系统没有任何地方会提醒你“这已经不是普通批量查询了”。

分批以后,单条 SQL 从:

1 条 SQL,几千个 ID

变成:

多条 SQL,每条最多 500 个 ID

这不是终极优化,因为总查询量还在。但它能先解决几个生产风险:

单条 SQL 文本可控。
数据库解析压力可控。
单次网络包可控。
慢 SQL 形态可控。
其他复用批量方法的调用方也能受益。

这里还有一个边界:分批必须继续保留租户条件。

不要为了复用 listByIds 之类的通用方法,把查询退化成:

WHERE id IN (...)

在 SaaS 系统里,商品、订单、库存、报表这类商户数据查询必须始终带租户条件:

WHERE merchant_id = ?
  AND id IN (...)

性能优化不能破坏数据隔离。

7. 方案二:列裁剪,别把整行商品资料拖出来

第二个低风险优化是列裁剪。

报表生成通常只需要商品资料的一部分字段:

商品名称
商品编码
商品分类
商品类型
单位或规格展示字段

但旧查询经常是整行返回。

商品资料表越复杂,字段越多,全字段查询的成本越明显。尤其是一些长文本、图片地址、扩展配置、状态字段,在报表回填里可能根本用不到。

所以查询可以从:

SELECT *
FROM product_profile
WHERE merchant_id = ?
  AND id IN (...);

改成:

SELECT id,
       major_name,
       minor_name,
       product_code,
       product_group_id,
       type
FROM product_profile
WHERE merchant_id = ?
  AND id IN (...);

列裁剪的收益通常没有“减少 ID 数量”那么大,但它胜在风险低。

只要回填字段梳理清楚,它不会改变报表行数,也不会改变统计金额,只是减少 IO 和对象构建成本。

8. 方案三:按需加载,真正减少 ID 数量

更彻底的方案是按需加载。

报表生成前通常已经拿到了事实数据,比如:

销售商品行
退单商品行
库存变动或库存快照

那么商品资料查询就不应该从“商户历史全量商品”开始,而应该从报表事实反推维度集合:

报表需要展示哪些商品?
-> 收集这些商品对应的商品资料 ID
-> 批量查询商品资料
-> 回填展示字段

抽象成公式:

需要加载的商品资料 = 有业务事实的商品资料 ∪ 历史回显补齐所需商品资料

这样才能从根上减少 IN 列表长度。

但这一步必须和产品确认口径:

无销售、无退单、只有历史存在的商品,要不要出现在商品日报?

如果答案是“不需要”,按需加载就是最优方案。

如果答案是“需要”,那按需加载就不能直接上,否则报表行数会变。

9. 方案四:改 Cron 只能缓解,不能治本

还有一种常见建议是改调度时间。

比如库存日报和商品日报相隔 15 分钟都打到商品资料表,那就把其中一个任务错开。

这个方案不是没用,它能缓解同一窗口数据库压力。但它不能解决单条 SQL 过大的根因。

如果一个任务本身会生成几千 ID 的 IN,你把它从 01:30 挪到 02:00,它仍然是一条几千 ID 的 IN。

所以我会把调度调整归类为运维缓解,而不是代码主方案。

合理的顺序应该是:

先让单个任务的 SQL 形态健康。
再根据实际耗时调整任务窗口。
最后把任务窗口纳入持续观测。

10. 方案五:缓存不是第一优先级

商品资料读多写少,看起来很适合缓存。

但报表任务里的缓存要谨慎。

第一,报表任务通常是批量冷启动场景。缓存未必已经预热。

第二,商品资料涉及多租户、删除状态、历史回显和截止时间。如果缓存键设计粗糙,很容易出现数据不一致。

第三,缓存能减少数据库读取次数,但不能回答“为什么要加载这么多商品资料”。

所以缓存可以作为后续增强,不适合作为第一阶段主方案。

我更倾向先做:

分批上限
列裁剪
按需加载
任务观测

等这些基础治理做好,再判断缓存是否必要。

11. 报表任务治理:不要只治理一条 SQL

这次问题真正应该沉淀的,不是“某个查询方法加分批”,而是报表任务治理清单。

至少要把以下维度纳入设计:

维度 要回答的问题
时间 任务按服务器时区还是商户时区触发
业务日 报表日边界按哪个时区计算
任务窗口 同类重任务是否集中触发
分批 商户分批、数据分批、SQL 分批是否都有上限
口径 未售商品、退单-only 商品、已删商品是否展示
重算 近几天自动重算,历史数据如何手动回填
对账 优化前后关键指标是否一致
观测 慢 SQL、任务耗时、批次数、失败原因是否可追踪

report-large-in-governance.png

报表系统最怕两种状态:

计算逻辑散在各个 Service 里,没人知道最终口径。
任务每天都跑,但没人知道它跑了多久、查了多少、失败过几次。

大 IN 只是一个信号。它提醒我们:某个报表任务的输入规模已经超过了当初默认实现的承载范围。

12. 验证不能只看“不慢了”

报表优化的验证标准不能只有“慢 SQL 消失”。

至少要有四类验证。

第一,SQL 形态验证。

单条 IN 数量是否小于阈值。
是否仍然带租户条件。
是否做了列裁剪。
是否没有新增全表扫描。

第二,报表结果验证。

同一商户、同一报表日,优化前后销量一致。
销售额、成本、毛利等核心金额一致。
商品行数是否符合预期口径。
已删商品历史回显是否正常。

第三,任务窗口验证。

商品日报任务是否能稳定完成。
库存日报任务是否能稳定完成。
周报、月报在周一或月初是否叠加放大。
连续任务是否互相挤压。

第四,可观测性验证。

大批量查询是否有 warn 日志。
日志里是否能看到商户、ID 数量、批次数。
任务开始和结束是否可关联。
失败时是否知道是超时、锁等待、SQL 慢还是数据异常。

如果只看到慢 SQL 下降,却没有对比报表结果,那这次优化是不完整的。

报表系统不只是要快,更要能解释。

13. 一个我会接受的落地顺序

如果让我设计这次优化,我会按下面顺序落地。

Phase 0:保护底层批量查询

先给商品资料批量查询补上分批能力。

目标是:

任何调用方都不能再把无限 ID 拼进一条 SQL。

这一步不改变业务口径,适合快速上线。

Phase 1:报表链路列裁剪

梳理报表实际需要哪些商品字段,只查必要列。

目标是:

同样的 ID 数量下,减少 IO、网络和对象构建成本。

Phase 2:报表按需加载商品资料

基于销售、退单、库存等事实集合反推商品资料 ID。

目标是:

从根上减少报表维度加载规模。

但这一步必须先确认“未售商品是否展示”的业务口径。

Phase 3:任务窗口与重算治理

把报表任务的调度、重算、对账、日志和慢 SQL 观测纳入统一规范。

目标是:

下次不是靠人肉猜测哪个任务在 06:30 触发。

14. 常见反模式

这类问题里,我会特别避免几种做法。

第一,只改慢 SQL 阈值。

慢 SQL 阈值是观测口径,不是性能优化。

第二,只加索引。

如果查询条件已经是 merchant_id + id,索引可能不是主要矛盾。真正的问题是传入规模没有边界。

第三,直接按需查询但不确认口径。

性能好了,报表行数变了,客户对账发现历史数据不一致,问题会更大。

第四,改 Cron 后宣布优化完成。

错峰只能缓解峰值,不会让单条 SQL 更健康。

第五,缓存兜底一切。

缓存会引入一致性、失效和历史口径问题。没有先治理查询边界和报表口径,缓存只是把复杂度藏起来。

15. 小结

一条 product_profile 超大 IN SQL,表面是数据库问题,背后其实是报表任务治理问题。

这次排查给我的启发是:

先还原时间,不要被服务器时区误导。
再追调用链,不要只盯着 SQL 本身。
先做不改口径的技术止血,再做按需加载的模型优化。
报表优化必须同时验证性能和口径。
大批量查询方法必须有上限,不能把调用方的规模风险直接传给数据库。

很多后端优化不是把一条 SQL 写得更漂亮,而是把它为什么出现、在哪个任务里出现、是否符合业务口径、是否可观测,全部查清楚。

这样才算真正把问题关掉。

本文为作者原创,首发于掘金,阿里巴巴开发者社区 为同步发布版本。

相关文章
|
1月前
|
人工智能 自然语言处理 API
阿里云全模态模型解析:适合多模态理解、音视频分析、语音对话、语音翻译等全模态场景
本文介绍了阿里云百炼平台的全模态大模型体系,针对实时语音/视频对话、音视频内容分析、同声传译、声音复刻等复杂多模态业务场景,系统梳理三大产品系列(Qwen3.5-Omni、Qwen3-Omni-Flash、Qwen3.5-Livetranslate)的核心定位与选型逻辑。文章提供GPT、Gemini等主流闭源全模态模型向百炼生态平滑迁移的对位对照表,详解各场景适配模型、API类型(HTTP/WebSocket)及关键能力(Function Calling、联网搜索、思考模式)差异,汇总60余种语言支持矩阵,帮助开发者根据能力、成本、延迟与语种覆盖度等维度,精准匹配业务需求。
|
1月前
|
人工智能 JavaScript NoSQL
24.5万 Star、安装超2000万次,这套顶级Skills到底强在哪?
AI写代码越快,返工越多?问题不在模型不够强,而在缺乏工程规范。TypeScript开发者Matt Pocock开源的**skills**项目(24万Star、2030万次安装),将TDD、需求澄清、Bug复现等经典工程实践转化为53个可插拔AI工作模块,为Claude/Codex等编码Agent注入“软件工程纪律”,让AI不止会写,更懂怎么正确地写。
|
1月前
|
存储 弹性计算 运维
阿里云轻量应用服务器与 ECS 云服务器深度对比指南,差异、限制、新手选型、运维、实操命令与避坑指南
很多刚接触云计算的用户,在选购服务器的时候都会陷入一个疑问,同样都是算力实例,轻量应用服务器与ECS云服务器到底有什么不同。二者底层虽然存在一定关联,但是在产品定位、网络架构、计费模式、功能权限、使用限制上存在巨大差距。轻量应用服务器定位轻量化单机应用,面向个人、学生、小型初创者,追求开箱即用,降低上云门槛;ECS属于标准企业级算力产品,开放完整的底层能力,适配从开发测试到大规模集群业务的全场景需求。不少用户盲目跟风选购,要么买了轻量之后发现高级功能无法使用,业务扩容处处受限;要么选用ECS做简单个人项目,造成资源预算浪费。本文会从适用人群、业务场景、计费、网络、镜像、功能限制、成本、海外节点
241 1
|
26天前
|
缓存 JSON API
通义千问Qwen3.8全系列完整解析:模型能力、API实操、计费模式与业务选型避坑全指南
Qwen3.8系列大模型,依托百万级上下文窗口、原生图文视频多模态能力、深度思考推理、稳定函数工具调用、上下文缓存、异步批量处理等完整能力,覆盖从简单问答到复杂智能体开发的广阔业务场景。Max旗舰版本面向高复杂度任务,Flash版本兼顾性能、速度与成本,适配绝大多数线上业务。
357 0
|
1月前
|
人工智能 Linux 虚拟化
【新版】阿里云 GPU 云服务器 产品功能介绍及配置价格表
随着大模型推理、模型微调、AI视频生成、科学仿真、三维渲染等业务快速普及,普通CPU计算资源已经很难承载大规模并行浮点运算任务,GPU云服务器成为AI研发、高性能计算领域的核心基础设施。阿里云GPU云服务器依托第三代神龙计算架构,将高性能CPU与专业GPU加速硬件深度融合,实现算力资源即开即用、弹性伸缩,不需要投入高额硬件采购成本,就可以获取单卡至多卡集群的异构计算能力,覆盖从个人开发者小模型测试,到企业级千亿参数大模型训练的全场景算力需求。本文将完整梳理产品核心功能,区分不同规格族的定位差异,解析计费逻辑,附带完整的Linux实操命令,同时给出选型思路、落地建议与高频踩坑避坑要点,帮助使用者
290 0
|
1月前
|
人工智能 缓存 Shell
DeepSeek Harness v0.1全量实测:“一切皆插件”AI Agent底座,本地部署、实战项目与排错完整教程
大模型本身擅长思考与文本生成,但原生能力无法直接读写本地文件、执行终端命令、调用网页接口、做多层任务自检。很多AI编程工具仅仅封装固定的能力集合,扩展能力受限,想要增加新工具、修改执行流程就要改动大量源码。DeepSeek Harness(dsh)作为开源Agent运行底座正式发布,提出核心公式**Agent = Model + Harness**:模型负责推理思考,Harness作为“挽具”,承担上下文管理、工具调度、任务编排、自检反馈、权限护栏整套工程运行能力,口号为**一切皆插件**,模型、工具、会话、存储、UI全部以插件形式实现,开发者无需修改内核源码,即可自由替换、重组全部能力。搭配
324 0
|
1月前
|
自然语言处理 API 开发工具
阿里云Qwen3.8‑Max、Qwen3.7‑Max、Qwen3.7‑Plus、Qwen3.7‑Flash能力差异与选型建议
在大模型应用落地过程中,模型选型直接影响业务效果、响应速度、调用成本和系统稳定性。Qwen系列作为当前主流大模型产品线,覆盖从高难度复杂推理到高性价比大规模部署的不同场景,其中Qwen3.8‑Max、Qwen3.7‑Max、Qwen3.7‑Plus、Qwen3.7‑Flash是开发者和企业最常接触的四个主力版本。很多开发者在选型时容易只关注“Max最强”或“Flash最便宜”,忽略模型定位、推理深度、长上下文能力、工具调用稳定性、多模态支持、成本结构之间的差异,导致复杂任务效果不足,或者大规模调用成本失控。
353 0
|
1月前
|
安全 API 定位技术
外卖系统接入配送API方案:如何实现订单与配送服务高效对接
本文详解外卖系统接入第三方配送API的完整方案,涵盖架构设计、接口规范、PHP代码实现、状态回调、幂等处理、异常重试及多平台适配等核心环节,助力自建平台高效解耦订单与履约,降低配送体系建设成本。(239字)
|
1月前
|
存储 弹性计算 人工智能
阿里云ECS云服务器、GPU云服务器、轻量应用服务器租赁费用全解析:收费标准、计费模式与活动报价参考
企业与个人开发者在采购云服务器时,成本往往是核心考量因素。很多使用者在初次采购后,面对账单明细时常出现困惑,不清楚各项扣费来源,分不清ECS云服务器、轻量应用服务器、GPU计算实例三者之间计费差异,也不了解不同计费模式带来的成本波动。阿里云服务器整体分为ECS通用云服务器、轻量应用服务器、GPU算力服务器三大产品线,三者硬件资源能力、计费体系、适用场景差异明显。完整理解计费项、计费模式、常规定价、活动报价,能够帮助使用者匹配自身业务,避免不必要的资源浪费,实现业务稳定运行同时控制整体云资源开销。本文完整梳理三类服务器的收费构成、各类计费模式特性、价格参考区间,同时提供实操命令,方便开发者借助工
297 0
|
1月前
|
测试技术 Shell 开发工具
DeepSeek Harness完整实操指南:开源Agent运行框架从安装、模式选型到代码集成
大模型对话产品已经非常普及,但绝大多数对话产品仅仅停留在文本问答层面,模型只能输出文字,无法真正读写本地文件、执行终端命令、自动拆分多步骤任务完成复杂工作。想要让大模型真正操作本机环境,就需要一套Agent运行时框架。DeepSeek Harness(简称DSH),就是2026年8月开源的Agent运行框架,目前处于开发者预览阶段,它的核心思想是**模型负责思考推理,Harness负责执行真实环境操作**。
539 0