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

pra*_*gan 4 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';
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

现在我将查询更改为以下格式[交换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 ) ; 
Run Code Online (Sandbox Code Playgroud)

相应的解释计划如下,

在此输入图像描述

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

提前致谢!

Jon*_*ler 5

Oracle 12c:

该功能NO_ROOT_SW_FOR_LOCALUSER_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);
Run Code Online (Sandbox Code Playgroud)

这两个子执行计划不仅仅是切换,它们发生了重大变化,总数也不同.与大多数数据字典查询一样,计划很大,此处不显示266行输出.

源代码USER_PROCEDURES包含奇数代码 ... from NO_ROOT_SW_FOR_LOCAL(INT$DBA_PROCEDURES) ....NO_ROOT_SW_FOR_LOCAL移除后,计划差异消失 .

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

11克: