写点什么

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

作者:数据库砖家
  • 2025-04-22
    广东
  • 本文字数:1134 字

    阅读完需:约 4 分钟

【问题分类】执行计划 / 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);
复制代码

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

-- 参数为 intSELECT * FROM tmp2 WHERE c2 = :1;-- 参数为 doubleSELECT * 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 监控工具时,注意不要误解“多个执行计划 = 多次执行”,要结合上下文综合判断。

用户头像

还未添加个人签名 2025-04-09 加入

还未添加个人简介

评论

发布
暂无评论
YashanDB知识库|一个 SQL 多个执行计划?绑定参数背后的优化器逻辑别忽略_数据库·_数据库砖家_InfoQ写作社区