Oracle 执行计划变更

Posted

技术标签:

【中文标题】Oracle 执行计划变更【英文标题】:Oracle execution plan changing 【发布时间】:2016-11-03 10:37:10 【问题描述】:

我有一个问题:

             SELECT COUNT(1)
             FROM registration r,
                  proxy p
             WHERE r.participant_code = p.participant_code
               AND r.proxy_type = p.proxy_type
               AND r.proxy_value = p.proxy_value
               AND r.proxy_sequence= p.proxy_sequence

表“proxy”的连接条件中使用的所有四个字段都在“proxy”主键中。查询的执行计划一直使用主键进行扫描,但是从一瞬间它突然改变了全表扫描的索引扫描。

在该查询稍作更改之后(加入 'r.proxy_value = p.proxy_value' 和 'r.proxy_type = p.proxy_type' 交换位置):

             SELECT COUNT(1)
             FROM registration r,
                  proxy p
             WHERE r.participant_code = p.participant_code
               AND r.proxy_value = p.proxy_value                   
               AND r.proxy_type = p.proxy_type
               AND r.proxy_sequence= p.proxy_sequence

实际上这两个查询是等价的。但是,在此更改之后,第二个查询的执行计划开始使用索引扫描而不是完全扫描。

现在我有一个非常具体的问题:

Oracle 是否会重新编译第二个查询,是否会导致查询执行计划发生变化?

【问题讨论】:

这两个查询显然等效/相同,但WHERE 子句中的条件顺序除外。虽然直觉上人们可能认为它们是相同的,但我会让它们都相同并重新测试(是的,我同意你的观点,这似乎是一个非常业余的评论,但我一生中曾多次惊讶于这种类型的东西)。 你知道其实我已经测试过这个场景(是的行为已经改变,还请注意,因为我无法控制 Oracle 执行计划管理机制,所以很难重新测试),什么我需要详细解释 Oracle 如何处理这种情况。对 Oracle 文档的任何参考将不胜感激。 我不确定我明白你的意思。您是否使两个选择相同(通过更改WHERE 子句中的条件顺序)?如果是,您是否观察到它们有不同的执行计划? 第一步:在干净的数据库上我插入一些测试数据执行两个查询,两个查询是相同的。第二步:在干净的数据库上,我从进行批量插入和选择的 java 应用程序进程执行。在某个时间点,我意识到这个过程变得太慢了。我使用 dbms 工具检查执行计划,发现查询进行全扫描而不是索引。我替换了上面提到的查询,然后它开始使用索引(注意我没有清理数据库,它已经有大约 100 万条记录) 当您解释两者的计划时,Oracle 是否会不断生成不同的计划,或者您仅在第一次执行时观察到这种情况,然后为两个查询获得相同的计划?如果第二个是您的情况,我会说第一个是通过完整扫描生成的,因为没有表的统计信息。 【参考方案1】:

Oracle 现在默认使用基于成本的优化器 (CBO),而之前的基于规则的优化器在数据仓库场景中的可预测性更高,但能力却大大降低。

一般来说,CBO 引入了“计划稳定性”问题,而 RBO 的计划始终保持不变。

使用 CBO 意味着执行计划可以并且将会根据统计数据和/或动态抽样数据的变化自行改变。实际上有一些工具可以监控计划切换历史记录(例如lab128)。

我在查看您的查询时注意到的另一点:没有过滤器,因此根据您的实际主键是什么,索引扫描可能很少使用。

【讨论】:

@mvb13 - 这也是我的猜测,改变的是基础数据。您是否能够在某个时间点根据完全相同的数据生成解释计划并进行比较? (请记住,如果您在两个不同的会话中运行这两个查询,即使是在完全相同的时间,如果其中一个或两个会话有/有未提交的事务,它们的数据可能仍然不同)。

以上是关于Oracle 执行计划变更的主要内容,如果未能解决你的问题,请参考以下文章

Oracle固定SQL的执行计划---SQL Profile

如何解析oracle执行计划

Oracle如何查看执行计划

Oracle执行计划总结

Oracle执行计划

一个执行计划异常变更的案例 - 前传