Database Oracle执行计划更改

Database Oracle执行计划更改,database,oracle,Database,Oracle,我有一个问题: 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_valu

我有一个问题:

             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\u value=p.proxy\u value”和“r.proxy\u type=p.proxy\u type”合并在一起,其中已交换):

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

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


Oracle是否会重新编译第二个查询,并导致查询执行计划的更改?

Oracle现在默认使用基于成本的优化器(CBO),而以前的基于规则的优化器更容易预测,但在数据仓库场景中的能力要差得多

总的来说,国会预算办公室引入了“计划稳定性”问题,而国会预算办公室的计划始终保持不变

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


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

除了
WHERE
子句中的条件顺序外,这两个查询显然是等价/相同的。虽然直觉上人们可能会认为它们是一样的,但我会让它们完全相同并重新测试(是的,我同意你的观点,这是一个非常业余的评论,但我一生中对这类事情感到惊讶的次数太多了)(是的,行为已经改变,请注意,重新测试非常困难,因为我无法控制Oracle执行计划管理机制),我需要的是详细解释Oracle如何处理这种情况。如有任何关于Oracle文档的参考,我们将不胜感激。我不确定我是否理解您的意思。您是否将两个选项都选择相同(通过更改
WHERE
子句中条件的顺序)?如果是,您是否观察到它们的不同执行计划?第一步:在clean database上插入一些测试数据执行两个查询,两个查询都是相同的。第二步:在clean database上,我从java应用程序进程执行,该进程进行批量插入和选择。在某个时间点,我意识到该进程变得太慢。我检查Excution计划使用dbms工具,发现查询进行完全扫描而不是索引。我按照上面提到的方法替换查询,然后它开始使用索引(注意,我没有清理数据库,它已经有大约100万条记录)当您解释这两个查询的计划时,Oracle是否一直在生成不同的计划,或者您只是在第一次执行时才观察到这种情况,然后才为这两个查询获得相同的计划?如果第二个查询是您的情况,我会说第一个查询是通过完全扫描生成的,因为表中没有统计信息。@mvb13-这也是我的猜测,更改的是参考数据ng数据。您是否能够在某个时间点基于完全相同的数据生成解释计划,并对其进行比较?(请记住,如果您在两个不同的会话中运行这两个查询,即使在完全相同的时间,如果其中一个或两个会话有/有未提交的事务,则它们的数据可能仍然不同)。
             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