ITPub博客

首页 > 数据库 > 数据库开发技术 > YashanDB知识库|一个 SQL 多个执行计划?绑定参数背后的优化器逻辑别忽略

YashanDB知识库|一个 SQL 多个执行计划?绑定参数背后的优化器逻辑别忽略

原创 数据库开发技术 作者:makabala 时间:2025-04-22 19:08:35 0 删除 编辑

【问题分类】执行计划 / SQL优化

【关键词】绑定变量、执行计划、v$sql、plan_hash_value、anlcontext、共享池

一、问题现象

在 TPCC 测试过程中发现:

同一条 SQL 使用绑定变量时,在 v$sql 视图中出现了  多个执行计划(plan_hash_value);

进一步观察,每个 plan 对应的 executions、cpu_time、elapsed_time 等统计信息  是相同的。

引发疑问:

同一个 SQL,为什么会出现多个执行计划?这些执行信息统计的是每个 plan 还是所有 plan 的总和?

二、现象验证:绑定参数触发不同执行计划

示例建表:

CREATE TABLE tmp2 (
c1 INT, c2 DOUBLE, c3 INT, c4 INT,
c5 INT, c6 INT, c7 INT, c8 TIMESTAMP,
c9 VARCHAR(500), c10 INT
);

使用如下两种方式绑定参数:

-- 参数为 int
SELECT * FROM tmp2 WHERE c2 = :1;
-- 参数为 double
SELECT * FROM tmp2 WHERE c2 = :1;

虽然 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 对象,管理其执行状态与统计信息。

关键结构:

struct anlcontext {
planContexts[];       // 不同执行计划列表
stats { ... }         // 包括 iostat、timestat、runstat 等指标
}

所有执行计划共享一个 stats 结构;

即便有多个 plan_hash_value,统计信息仍归属于同一个 sqlcontext。

执行过程简述:

doExecute →
fetchPlanWithPreProj →
anlFetchPlan →
doAnlFetchPlan →
fetchSelectPlan

每次执行会根据 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 监控工具时,注意不要误解“多个执行计划 = 多次执行”,要结合上下文综合判断。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70045450/viewspace-3082093/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2025-04-10

  • 博文量
    231
  • 访问量
    229291