YashanDB 知识库|一个 SQL 多个执行计划? 绑定参数背后的优化器逻辑别忽略
【问题分类】执行计划 / SQL 优化
【关键词】绑定变量、执行计划、v$sql、plan_hash_value、anlcontext、共享池

一、问题现象
在 TPCC 测试过程中发现:
同一条 SQL 使用绑定变量时,在 v$sql 视图中出现了 多个执行计划(plan_hash_value);
进一步观察,每个 plan 对应的 executions、cpu_time、elapsed_time 等统计信息 是相同的。
引发疑问:
同一个 SQL,为什么会出现多个执行计划?这些执行信息统计的是每个 plan 还是所有 plan 的总和?

二、现象验证:绑定参数触发不同执行计划
示例建表:
使用如下两种方式绑定参数:
虽然 SQL 文本完全一致,但因参数类型不同,数据库生成了两个不同的执行计划(plan_hash_value 不同)。
三、为什么参数类型不同会触发多个计划?
YashanDB 会根据绑定变量的 类型信息 决定是否复用现有执行计划。
类型一致:复用已有 plan;
类型不一致:重新生成新的 plan,并缓存至 sqlpool。
这在性能调优中非常关键,特别是 bind peek / plan stability 场景中。
四、那统计信息是不是就分散了?
令人意外的是:
尽管存在多个 plan_hash_value,但 v$sql 中显示的 executions、elapsed_time 等统计值是一致的。
这说明这些统计信息并不是“按 plan 统计”,而是以 SQL 为单位汇总记录的。
五、核心机制解析:anlcontext 与 sqlpool
YashanDB 中,每条 SQL 在执行时会生成一个 anlcontext 对象,管理其执行状态与统计信息。
关键结构:
所有执行计划共享一个 stats 结构;
即便有多个 plan_hash_value,统计信息仍归属于同一个 sqlcontext。
执行过程简述:
每次执行会根据 pool 中已有的 context 判断是否重用 plan,或生成新 plan 加入 planContexts。
六、SQL 共享池的内存管理方式
YashanDB 的共享池按如下结构划分内存区域:

SQL 上下文结构体 anlcontext 就存储在 sql pool 中。

七、实战建议与经验总结
1.同一个绑定变量 SQL 出现多个 plan 是合理现象,由参数类型差异导致;
2.v$sql 的统计值是全局共享的,无法通过 plan_hash_value 做精确区分;
3.若需做执行计划层级的统计分析,需结合 planContexts[] 深度日志分析;
4.推荐对频繁执行的 SQL 保持参数类型一致,以提高执行计划复用率;
5.使用 SQL 监控工具时,注意不要误解“多个执行计划 = 多次执行”,要结合上下文综合判断。
评论