news 2026/8/25 15:18:50

分区裁剪失效的常见原因——时间序列表的边界SQL、执行计划与修复实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
分区裁剪失效的常见原因——时间序列表的边界SQL、执行计划与修复实战

文章目录

    • 每日一句正能量
    • 1. 背景与问题:明明按天分区,为什么查一天却扫描了十二个月?
    • 2. 环境与数据:先明确分区键、数据类型和边界语义
      • 2.1 第一件事:确认真正的分区键
      • 2.2 第二件事:确认数据类型
      • 2.3 第三件事:检查裁剪开关
    • 3. 复现过程:六类边界 SQL 怎样让裁剪能力下降
      • 3.1 案例一:对分区键做 CAST
      • 3.2 案例二:date_trunc包裹分区键
      • 3.3 案例三:时区转换写在列上
      • 3.4 案例四:错误使用 BETWEEN
      • 3.5 案例五:OR中存在不受分区键约束的分支
      • 3.6 案例六:可空参数模板
      • 3.7 Prepared Statement还要单独验证
    • 4. 方案实施:怎样把分区条件写成“优化器容易证明”的形式
      • 4.1 第一原则:分区键尽量保持裸列
      • 4.2 第二原则:把函数作用在常量侧
      • 4.3 第三原则:DATE/TIMESTAMP类型一致
      • 4.4 第四原则:统一使用半开区间
      • 4.5 第五原则:按查询主入口选择分区键
      • 4.6 第六原则:分区粒度不要过细
      • 4.7 第七原则:索引不能替代分区裁剪
      • 4.8 第八原则:执行计划必须数分区,而不是只看顶层成本
      • 4.9 第九原则:检查 enable_partition_pruning
      • 4.10 第十原则:传统继承表与声明式分区要区分
    • 5. 结果对比:从12个分区18.6秒,降到1个分区420ms
      • E0:函数包裹分区键
      • E1:改成直接范围
      • E2:日报缩成一天半开区间
      • E3:拆分 OR
      • E4:按参数形态拆 SQL
      • E5:只加索引,不修谓词
      • 5.1 实验汇总
      • 5.2 不只看Execution Time,还要看Planning Time
      • 5.3 分区裁剪后并行计划可能自然消失
      • 5.4 Rows Removed by Filter也能证明裁剪失败
    • 6. 风险与复盘:分区裁剪优化最危险的是“性能修好了,时间口径却改错了”
      • 6.1 风险一:时区边界错误
      • 6.2 风险二:DATE与TIMESTAMP边界混淆
      • 6.3 风险三:BETWEEN重复午夜数据
      • 6.4 风险四:OR拆分改变重复语义
      • 6.5 风险五:只在Literal SQL验证
      • 6.6 风险六:分区键选错
      • 6.7 风险七:分区太多
      • 6.8 风险八:把 enable_partition_pruning 当业务开关
  • 推荐的分区裁剪诊断顺序
  • 回退方案
  • 最终复盘
  • 附录 A:推荐日边界
  • 附录 B:检查裁剪开关
  • 附录 C:执行计划验证
  • 附录 D:最低验收门禁

每日一句正能量

心有所爱,无畏时光。
当一个人内心有了真正热爱的人或事,他便拥有了对抗时间流逝与虚无的铠甲。热爱如同一个稳固的精神内核,能消解时光带来的焦虑、迷茫与恐惧,让人在变化中获得恒常的定力。

主题:分区查询 / 时间序列表 / Partition Pruning
重点:范围分区、分区键、时间边界、函数与 CAST、时区、Prepared Statement、OR 条件、enable_partition_pruning、执行计划、Buffers、P95/P99
适用场景:KingbaseES 上的交易流水、日志、指标、审计、订单历史、IoT 时序数据等按日期或时间字段进行 Range 分区的大表。


1. 背景与问题:明明按天分区,为什么查一天却扫描了十二个月?

时间序列表常见设计:

每天/每月一个分区

例如:

ts_event ├── 2026-01 ├── 2026-02 ├── ... └── 2026-12

业务只查询:

2026-08-01

按理说:

只需要访问8月或者8月1日对应分区

但线上计划却可能:

Append ├── Scan p202601 ├── Scan p202602 ├── ... └── Scan p202612

甚至:

12个分区全部参与

P95 从:

400ms

变成:

18s

很多人第一反应是:

分区失效了

然后开始:

加索引 开并行 调work_mem

但真正应该先问:

优化器能不能从WHERE条件中证明 “不可能命中其他分区”?

这就是 Partition Pruning 的核心。

KingbaseES 官方对象管理文档明确指出,范围分区通常和日期一起使用,数据库根据分区键的值范围将记录映射到各个分区;开发规范也明确建议,对经常按时间段查询的大表优先采用时间字段 Range 分区,并要求高频 SQL 尽量带有分区条件。

因此本文第一个结论是:

分区表本身并不会自动让查询变快。真正产生收益的是:SQL 谓词能够被优化器识别成与分区边界一致的条件,从而在规划期或执行期排除不相关分区。


2. 环境与数据:先明确分区键、数据类型和边界语义

示例表:

CREATETABLEts_event(event_idBIGINTNOTNULL,event_timeTIMESTAMPNOTNULL,tenant_idBIGINTNOTNULL,event_typeINTNOTNULL,payloadVARCHAR(500))PARTITIONBYRANGE(event_time);

逻辑上按天划分:

p20260801 [2026-08-01 00:00:00, 2026-08-02 00:00:00) p20260802 [2026-08-02 00:00:00, 2026-08-03 00:00:00)

KingbaseES 官方范围分区示例采用“上界小于”语义,日期范围通过VALUES LESS THAN类边界来定义。工程上最自然的查询写法正是:

[start, end)

也就是:

大于等于开始时间 小于下一个边界

而不是人为构造:

23:59:59.999999

这样的末秒值。


2.1 第一件事:确认真正的分区键

很多系统设计:

按event_time分区

业务 SQL 却过滤:

biz_time created_at receive_time

如果:

event_time

完全不在 WHERE 中,那么数据库没有依据排除分区。

这种问题不是:

裁剪算法坏了

而是:

分区键与查询入口不匹配

所以任何分区性能问题第一张表必须记录:

项目示例
分区键event_time
类型TIMESTAMP
分区粒度DAY
查询过滤列biz_time
是否同列

如果最后一项是:

后面的 SQL 微调可能只能治标。


2.2 第二件事:确认数据类型

时间列常见:

DATE TIMESTAMP TIMESTAMPTZ VARCHAR日期字符串

SQL 参数常见:

Java LocalDate LocalDateTime OffsetDateTime String

数据库真正收到什么类型,会影响:

隐式转换 表达式形态 分区边界比较

因此不能只看:

应用代码里的变量类型

还要看:

数据库计划里最终的条件表达式

2.3 第三件事:检查裁剪开关

KingbaseES 数据库参考手册提供:

enable_partition_pruning

参数,默认值为:

on

并且它是声明式分区表裁剪的独立控制项。传统继承表的constraint_exclusion与声明式分区并不是同一个机制;官方参考手册也明确提示,现代分区表的对应能力由enable_partition_pruning控制。

检查:

SHOWenable_partition_pruning;

如果人为关闭:

off

先解决这个问题。

但在生产事故中,更常见的情况是:

参数是on SQL谓词却无法产生理想裁剪

3. 复现过程:六类边界 SQL 怎样让裁剪能力下降

3.1 案例一:对分区键做 CAST

常见 SQL:

SELECT*FROMts_eventWHEREevent_time::date=DATE'2026-08-01';

业务表达很自然:

取8月1日所有记录

但是优化器看到的是:

CAST(event_time AS date)

而分区定义依据的是:

event_time

本身。

对于不同版本、不同表达式能力,优化器是否能完全推导出原始时间边界不能靠猜。

生产调优更稳妥的方式是直接表达:

WHEREevent_time>=TIMESTAMP'2026-08-01 00:00:00'ANDevent_time<TIMESTAMP'2026-08-02 00:00:00';

这时谓词和分区边界天然一致。


3.2 案例二:date_trunc包裹分区键

WHEREdate_trunc('day',event_time)=TIMESTAMP'2026-08-01 00:00:00'

这和上一类本质相同:

业务条件描述在“加工后的列”

而不是:

原始分区键

如果最终计划扫描大量子分区,最优先的修复就是:

把函数移出分区键

计算:

start end

两个常量/绑定参数。


3.3 案例三:时区转换写在列上

例如:

WHEREevent_time ATTIMEZONE'UTC'>=:local_start;

这个 SQL 有两个风险:

1. 对分区键做了表达式 2. 时间语义可能发生变化

更稳妥的方法:

业务本地时间 ↓ 应用/SQL入口计算成数据库分区键采用的时间基准 ↓ 绑定start_ts/end_ts ↓ 直接比较event_time

例如:

WHEREevent_time>=:utc_startANDevent_time<:utc_end;

这样:

时区转换

和:

分区边界判断

解耦。


3.4 案例四:错误使用 BETWEEN

很多日报 SQL:

WHEREevent_timeBETWEENTIMESTAMP'2026-08-01 00:00:00'ANDTIMESTAMP'2026-08-02 00:00:00';

BETWEEN两端通常都是包含语义。

那么:

2026-08-02 00:00:00

本身也在结果范围。

如果日分区边界:

8月2日00:00

已经属于下一个分区。

这会造成:

边界额外命中

更重要的是业务口径也可能重复。

例如日报:

8月1日

和:

8月2日

都把:

8月2日00:00:00

算进去。

所以时间范围最好统一:

[start, end)


3.5 案例五:OR中存在不受分区键约束的分支

WHERE(event_time>=:start_tsANDevent_time<:end_ts)ORevent_id=:event_id;

第一分支:

只需要一天

第二分支:

event_id可能在任何分区

从整个 OR 语义看:

任何分区都有可能命中event_id

因此不能指望:

只扫描时间范围对应分区

这时可以借鉴前面 OR 条件文章的思路:

SELECT...FROMts_eventWHEREevent_time>=:start_tsANDevent_time<:end_tsUNIONSELECT...FROMts_eventWHEREevent_id=:event_id;

两个分支独立规划。

但必须验证:

同一行同时满足两条分支时

是否需要去重。

如果不能证明互斥:

不要直接改UNION ALL

3.6 案例六:可空参数模板

框架很喜欢:

WHERE(:start_tsISNULLORevent_time>=:start_ts)AND(:end_tsISNULLORevent_time<:end_ts)

优点:

一个SQL模板支持所有参数组合

缺点:

优化器需要同时考虑参数为空和不为空

如果实际接口 99% 都带:

start/end

那么为了 1% 的无边界查询,把所有请求都变成一个复杂模板并不值得。

更稳定:

Q_TIME_BOUNDED Q_UNBOUNDED

拆成两个 SQL fingerprint。

这样:

有时间范围的SQL

天然保留清晰的分区条件。


3.7 Prepared Statement还要单独验证

应用里:

JDBC PreparedStatement

可能和手工 literal SQL 的规划行为不同。

因此必须用真实:

PREPARE / EXECUTE

或 JDBC/PBE 复现。

不能只在:

ksql里写死日期

然后断言生产一定裁剪同样的分区。

尤其上一系列文章已经讨论过:

Generic Plan / Custom Plan

参数敏感。

分区裁剪也应该和真实参数化方式一起验证。


4. 方案实施:怎样把分区条件写成“优化器容易证明”的形式

4.1 第一原则:分区键尽量保持裸列

优先:

event_time>=:start_tsANDevent_time<:end_ts

不优先:

date(event_time)=:day
to_char(event_time,'YYYYMMDD')=:d
event_time::date=:d
extract(monthfromevent_time)=8

这些写法不一定在所有版本里都百分之百无法裁剪,但工程上:

裸分区键 + 直接边界比较

最清晰、最稳。


4.2 第二原则:把函数作用在常量侧

错误思路:

date_trunc('day',event_time)=:d

更合理:

start = date_trunc(day,:input) end = start + 1 day

然后:

event_time>=:startANDevent_time<:end

也就是说:

加工查询参数,不加工分区键。


4.3 第三原则:DATE/TIMESTAMP类型一致

如果分区键:

TIMESTAMP

绑定参数尽量:

TIMESTAMP

而不是:

VARCHAR

让数据库自行猜转换。

同理:

TIMESTAMPTZ

要明确时区。

这种规范不仅帮助裁剪,也减少:

索引失效 隐式转换 时区Bug

4.4 第四原则:统一使用半开区间

日:

[2026-08-01, 2026-08-02)

月:

[2026-08-01, 2026-09-01)

年:

[2026-01-01, 2027-01-01)

SQL:

event_time>=:startANDevent_time<:end

优势:

没有微秒精度问题 没有边界重复 和Range分区上界逻辑天然一致

4.5 第五原则:按查询主入口选择分区键

官方开发规范明确建议,高频执行的 SQL 应尽量包含分区条件;对按时间范围检索的大表优先使用时间范围分区。

如果核心接口 90% 都是:

按biz_time查

却按:

ingest_time

分区。

那么长期应该评估:

分区设计本身是否错位

而不是永远用 SQL 技巧补救。


4.6 第六原则:分区粒度不要过细

按小时分区:

一年8760个分区

可能增加:

规划开销 对象数量 维护复杂度

KingbaseES 开发规范建议控制分区规模与分区数量,并提醒对象过多会扩大数据字典并影响整体效率。

所以:

裁剪越细越好

也不成立。

需要平衡:

单分区数据量 查询时间范围 维护周期 分区数量

4.7 第七原则:索引不能替代分区裁剪

假设:

12个分区全部扫描

每个分区都有:

(event_time, tenant_id)

索引。

索引可能把:

18秒

降到:

11秒

但真正正确的计划:

只扫描1个分区

可能:

0.4秒

两者不是一个量级。

所以:

分区裁剪是“不要访问不相关数据”,索引是“在已经访问的数据范围里更快找到记录”。这两个优化层次不能互相替代。


4.8 第八原则:执行计划必须数分区,而不是只看顶层成本

运行:

EXPLAIN(ANALYZE,BUFFERS,VERBOSE)SELECT...

重点:

Append / Merge Append 下面有多少子扫描 分区名字 actual loops Buffers Rows Removed by Filter Planning Time Execution Time

不同 KingbaseES 版本在:

运行期裁剪信息

的具体计划显示字段上可能有差异。

因此不要依赖:

某一个固定字段名

判断。

最可靠:

看实际参与扫描的子计划/分区

4.9 第九原则:检查 enable_partition_pruning

诊断实验:

SHOWenable_partition_pruning;

正常:

on

可以在测试环境做反向实验:

on vs off

验证:

当前SQL性能收益是否确实来自裁剪

但不要把:

关闭分区裁剪

作为任何长期优化手段。

KingbaseES 参考手册确认该参数是用户级布尔开关,默认开启。


4.10 第十原则:传统继承表与声明式分区要区分

如果历史系统使用:

INHERITS + CHECK

做老式分区。

裁剪还会涉及:

constraint_exclusion

官方参考手册说明,constraint_exclusion=partition主要针对传统继承子表与相关约束检查;声明式分区的等价机制由enable_partition_pruning单独控制。

所以排查:

老系统升级

时必须先确认:

这张“分区表”究竟是哪种实现

否则参数会查错方向。


5. 结果对比:从12个分区18.6秒,降到1个分区420ms

E0:函数包裹分区键

WHEREevent_time::date=DATE'2026-08-01'

示例计划:

12个月分区全部参与

Buffers:

980万

P95:

18.6s

E1:改成直接范围

WHEREevent_time>=TIMESTAMP'2026-08-01 00:00:00'ANDevent_time<TIMESTAMP'2026-09-01 00:00:00'

扫描:

1个月分区

Buffers:

82万

P95:

1.9s

E2:日报缩成一天半开区间

WHEREevent_time>=:day_startANDevent_time<:next_day

扫描:

目标日分区

Buffers:

11万

P95:

420ms

这才是真正发挥:

时间分区

价值。


E3:拆分 OR

原:

time condition OR event_id

改成:

时间范围分支 UNION event_id分支

时间分支可以独立裁剪。

P95:

710ms

注意:

UNION/UNION ALL

必须先验证重复语义。


E4:按参数形态拆 SQL

原:

:start IS NULL OR ...

拆成:

Q_WITH_TIME Q_WITHOUT_TIME

有边界查询:

始终保留直接分区条件

P99:

明显收敛

这对:

高频API

往往比让一条万能 SQL 支持所有参数组合更稳定。


E5:只加索引,不修谓词

示例:

仍扫描12个分区

Buffers:

640万

P95:

10.9s

有改善。

但远不及:

真正裁剪

5.1 实验汇总

实验条件扫描分区BuffersP95
E0event_time::date=:d12980万18.6s
E1直接月范围182万1.9s
E2类型一致的日半开区间111万0.42s
E3OR拆分目标分区+独立ID分支19万0.71s
E4参数形态拆SQL目标分区9.5万0.36s
E5仅加索引12640万10.9s

以上为方法演示数据,不是生产实测。


5.2 不只看Execution Time,还要看Planning Time

如果:

几千个分区

即使执行期最终只访问一个分区:

规划成本

也可能上升。

所以极端分区数系统要记录:

Planning Time Execution Time

两者。

官方开发规范也明确提醒,不应让单表分区数量无限增长,因为对象过多会影响数据库整体效率。


5.3 分区裁剪后并行计划可能自然消失

裁剪失效:

扫描12个月

优化器可能:

Parallel Append Parallel Seq Scan

修复后:

只扫描1天

计划可能不再使用:

并行

这不是性能退化。

而是:

工作量已经小到不值得启动Worker

官方并行查询文档也强调,并行存在启动和进程间通信成本,不是 Worker 越多越快。


5.4 Rows Removed by Filter也能证明裁剪失败

如果多个分区节点:

读了大量行 然后Rows Removed by Filter非常高

说明数据库:

先访问 后过滤

真正理想的是:

根本不访问无关分区

这就是:

Partition Pruning

和普通 Filter 的本质区别。


6. 风险与复盘:分区裁剪优化最危险的是“性能修好了,时间口径却改错了”

6.1 风险一:时区边界错误

应用:

Asia/Shanghai

数据库:

UTC

如果直接把:

2026-08-01 00:00

绑定成 UTC:

会少/多8小时

所以修裁剪时必须同时验证:

业务时区 数据库时区 JDBC时区 分区键存储语义

6.2 风险二:DATE与TIMESTAMP边界混淆

DATE:

一天

TIMESTAMP:

精确时间点

不要依赖隐式转换猜测。

应明确:

start/end类型

6.3 风险三:BETWEEN重复午夜数据

日报最典型。

修复:

统一 [start,end)

并在:

00:00:00 23:59:59.999...

边界做测试。


6.4 风险四:OR拆分改变重复语义

原 OR:

同一行只出现一次

UNION ALL:

可能两次

必须:

证明互斥 或使用UNION去重

6.5 风险五:只在Literal SQL验证

手工:

日期写死

裁剪很好。

应用:

PreparedStatement

却慢。

这时必须:

从真实JDBC/PBE链路复现

不能只说:

数据库本地测试没问题

6.6 风险六:分区键选错

如果大量核心查询天然不带:

当前分区键

说明:

表设计与查询模型长期错位

应该评估:

重新分区 二级分区 汇总层 冷热分离

而不是一直靠特殊 SQL。


6.7 风险七:分区太多

超细粒度:

可以更精确裁剪

但会提高:

DDL维护 统计采集 规划 数据字典 备份

成本。

分区设计必须同时服务:

查询 维护 生命周期

6.8 风险八:把 enable_partition_pruning 当业务开关

该参数是优化器能力开关。

正常生产:

应该保持开启

如果为了某一条 SQL:

关闭

会伤害大量其他分区查询。

它适合:

诊断对照

不适合:

业务级长期调优

推荐的分区裁剪诊断顺序

遇到分区查询慢:

1. 确认分区键和分区类型 2. SHOW enable_partition_pruning 3. EXPLAIN ANALYZE数实际扫描分区 4. 看分区键有没有被函数/CAST包裹 5. 检查参数类型和时区 6. 改成[start,end)直接范围 7. 检查OR/可空参数 8. 用真实PreparedStatement复测 9. 记录Buffers/P95/P99 10. 再决定是否需要索引/并行

顺序不能反。

如果第一步没裁剪:

先加十个索引

只是让:

错误访问的数据稍微快一点

回退方案

如果边界 SQL 改写上线后出现:

漏数 重复 跨天错误 时区错误 P99回归

执行:

1. 停止扩大新SQL 2. Feature Flag/Query Mapping恢复旧SQL 3. 保存新旧执行计划 4. 保存真实Bind参数类型 5. 验证午夜/月末/时区边界 6. 如果用了UNION,检查重复集合 7. 新索引暂时保留,完成依赖检查后再决定删除

尤其:

时间边界错误

优先级高于:

性能收益

最终复盘

分区裁剪的本质可以用一句非常简单的话解释:

优化器必须能够证明某个分区不可能包含结果

最容易证明的 SQL:

partition_key>=:startANDpartition_key<:end

最难证明的往往是:

函数(partition_key) CAST(partition_key) 时区表达式(partition_key) 复杂OR 可空参数模板

所以:

时间分区 SQL 的最佳实践不是“把日期条件写出来就行”,而是让分区键以原始类型、直接范围、与分区边界一致的形式出现在谓词中。

如果只记住一句话:

分区裁剪优化不是让已扫描的分区更快,而是让无关分区从执行计划里彻底消失;真正值得监控的不是“有没有分区表”,而是“一条只查一天的 SQL 到底实际扫描了几个分区”。

这也是为什么生产验收必须记录:

扫描分区数 + Buffers + actual rows + Planning Time + Execution Time + P95/P99

而不能只看:

SQL最终返回多少行

附录 A:推荐日边界

WHEREevent_time>=:day_startANDevent_time<:next_day

附录 B:检查裁剪开关

SHOWenable_partition_pruning;

附录 C:执行计划验证

EXPLAIN(ANALYZE,BUFFERS,VERBOSE)SELECT...FROMts_eventWHEREevent_time>=:start_tsANDevent_time<:end_ts;

重点看:

Append / Merge Append 实际子分区扫描 Buffers Rows Removed by Filter Planning Time Execution Time

附录 D:最低验收门禁

[ ] KingbaseES版本已记录 [ ] 兼容模式已记录 [ ] 分区键已确认 [ ] enable_partition_pruning=on [ ] 目标SQL实际扫描分区数已记录 [ ] 分区键未被不必要函数/CAST包裹 [ ] DATE/TIMESTAMP/TIMESTAMPTZ类型已确认 [ ] 时间区间采用[start,end) [ ] JDBC参数类型已验证 [ ] OR/可空参数已评估 [ ] 午夜/月末边界结果差异=0 [ ] 时区边界结果正确 [ ] P95/P99达到SLA [ ] 回退SQL已准备

转载自:https://blog.csdn.net/u014727709/article/details/163950471
欢迎 👍点赞✍评论⭐收藏,欢迎指正

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 15:15:25

共享内存呀

共享内存&#xff08;Shared Memory&#xff09;是 IPC 进程间通信 方式之一&#xff0c;原理&#xff1a;在内核开辟一块物理内存&#xff0c;多个进程将这块内存映射到自己的虚拟地址空间&#xff0c;直接读写内存&#xff0c;无需内核拷贝数据&#xff0c;速度最快&#xff…

作者头像 李华
网站建设 2026/8/25 14:58:41

JVM规范第 3 章:从 Java 源码到字节码

本教程基于 Oracle 官方《The Java Virtual Machine Specification》&#xff08;Java SE 26&#xff09;第 3 章《Compiling for the Java Virtual Machine》整理编写。这一章本身不是规范性内容&#xff0c;而是由 Oracle 的 javac 示例展示「Java 源码是怎么变成 JVM 指令的…

作者头像 李华
网站建设 2026/8/25 14:55:25

Agent Content Protocol: 一种基于 RFC 2046 的内容封装规范

Agent Content Protocol: 一种基于 RFC 2046 的内容封装规范 2026-08-22 Agent Content Protocol: 一种基于 RFC 2046 的内容封装规范 版本&#xff1a;0.5.0-draft1. 协议定位与核心宣言 1.1 定位 ACP 定义了一种可互操作的 Agent 消息内容信封。它规定了如何将一个 JSON 控制…

作者头像 李华
网站建设 2026/8/25 14:51:44

SkillGo,支持多用户与独立沙箱执行的 Skill 平台

一、为什么要做 SkillGo&#xff1f; 聚焦于解决&#xff1a; 创造一个私有化部署的社区&#xff0c;Skill 获得以后&#xff0c;在社区中怎样管理、怎样运行、怎样隔离&#xff0c;以及怎样将skill配置成可以接入业务系统的api。 这是 SkillGo 出现的原因。 GitHub&#xff1…

作者头像 李华