交换SELECT语句时,Oracle JOIN操作性能会发生变化

时间:2014-01-13 04:48:07

标签: sql oracle join sql-execution-plan

在研究Oracle查询解析和性能时,我遇到了以下行为。我使用了以下查询,

SELECT 1 
FROM USER_PROCEDURES 
WHERE OBJECT_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), 1, INSTR( UPPER('Client_Sys.Clear_Info'), '.' ) - 1 ) 
AND PROCEDURE_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), INSTR( UPPER('Client_Sys.Clear_Info' ),'.' ) + 1 ) 
UNION 
SELECT 1 
FROM USER_OBJECTS 
WHERE OBJECT_NAME = UPPER('Client_Sys.Clear_Info') 
AND OBJECT_TYPE = 'PROCEDURE';

上述查询的解释计划如下,

enter image description here

现在我将查询更改为以下格式[交换SELECT语句],

SELECT 1 
FROM USER_OBJECTS 
WHERE OBJECT_NAME = UPPER('Client_Sys.Clear_Info') 
AND OBJECT_TYPE = 'PROCEDURE'
UNION 
SELECT 1 
FROM USER_PROCEDURES 
WHERE OBJECT_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), 1, INSTR( UPPER('Client_Sys.Clear_Info'), '.' ) - 1 ) 
AND PROCEDURE_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), INSTR( UPPER('Client_Sys.Clear_Info' ),'.' ) + 1 ) ; 

对应的解释计划如下,

enter image description here

运营成本之间存在显着差异。这可能是一个非常基本的事情,但由于我是Oracle [或任何数据库的东西]的新手,这对我来说是一个难题。希望你能帮助我解决这个问题。

提前致谢!

3 个答案:

答案 0 :(得分:5)

Oracle 12c:

NO_ROOT_SW_FOR_LOCAL中的USER_PROCEDURES函数似乎是造成差异的原因。

通常,更改谓词,FROM子句中的表或UNION语句中的查询块等内容的顺序对执行计划没有任何有意义的影响。  使用UNION时,某些子计划可能会被翻转,但总费用会相同。

对于这种特定情况,首先将语句简化为:

explain plan for select 1 from user_procedures union select 1 from dual;
select * from table(dbms_xplan.display);

explain plan for select 1 from dual union select 1 from user_procedures;
select * from table(dbms_xplan.display);

这两个子执行计划不仅仅是切换,它们都有显着改变,总数也不同。与大多数数据字典查询一样,计划很大,此处不显示266行输出。

USER_PROCEDURES的源代码包含奇数代码... from NO_ROOT_SW_FOR_LOCAL(INT$DBA_PROCEDURES) ...。 <{1}}被删除后,计划差异就消失了。

我不知道那个函数做了什么,我找不到任何引用它。 DBA_OBJECTS,DBA_SOURCE,support.oracle.com甚至谷歌都没有。这是我们可以挖掘没有任何严重的黑客攻击。如果这个成本差异是一个问题,那么您将需要向Oracle提出服务请求。

<强>11克:

答案 1 :(得分:2)

不是直接的答案,但我会尝试重写查询,以避免总是执行这两个部分:

select 1
from   dual
where exists (
        SELECT 1 
        FROM USER_OBJECTS 
        WHERE OBJECT_NAME = UPPER('Client_Sys.Clear_Info') 
        AND OBJECT_TYPE = 'PROCEDURE') or
      exists (
        SELECT 1 
        FROM USER_PROCEDURES 
        WHERE OBJECT_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), 1, INSTR( UPPER('Client_Sys.Clear_Info'), '.' ) - 1 ) 
        AND PROCEDURE_NAME = SUBSTR( UPPER('Client_Sys.Clear_Info' ), INSTR( UPPER('Client_Sys.Clear_Info' ),'.' ) + 1 )); 

答案 2 :(得分:1)

Oracle 11G:

在我看来或到目前为止我看到的内容,UNION或VIEW语句处理更多行但开销可忽略不计。 同样只是比较计划的成本将不会给你最好的计划,即使它们是同时触发的两个不同的查询,相同的数据库,相同的设置等 它只是一个指示因素并诱导观察效应。

当您运行这两个查询时,您是否发现执行时间有任何重大变化?我发现没什么。

但如果你问为什么交换时的成本有差异,这是我的两分钱。

On plan 1, Cost was 161, CPU cost was 74M, IO Cost was 151
On plan 2, Cost was 161, CPU cost was 23M, IO Cost was 6

我发现在交换时处理选择没有区别,但UNION是计划不同的点。 如上所述,成本差异是由于UNION和VIEW上的额外行处理。