【发布时间】: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 是否会不断生成不同的计划,或者您仅在第一次执行时观察到这种情况,然后为两个查询获得相同的计划?如果第二个是您的情况,我会说第一个是通过完整扫描生成的,因为没有表的统计信息。