2016-03-03 45 views
0

在我的生产环境我有一个有意义的差异,当我在选择直接调用的函数和函数Oracle的性能,当我“包装”的选择,然后调用然后函数外(下面我告诉你两个简单的例子)与在选择

在第一种情况下(当直接调用函数时),结果查询在35秒内结束。

在第二种情况下(函数包装),结果在7秒内结束。

当然,查询是exatcly相同,结果行也是一样的。

在两种方式中调用同一个函数是有区别的吗?

慢版:

select col1, col2, myFun(col3) 
    from aTable; 

快速版本

select col1, col2, myFun(col3) 
    from (select col1, col2, col3 
      from aTable); 
+0

你确定那才是真正的查询?没有'WHERE'或'JOIN'或类似的东西? – Thilo

+0

@ Mistre83:你有没有试过在两个陈述上做一个'EXPLAIN'? –

+0

函数到底是什么?高管的计划是什么?函数执行多少次? – ibre5041

回答

2

假设有100万行的aTable,但你真正的查询有一个返回只有10行的WHERE子句:

select col1, col2, myFun(col3) 
    from aTable 
    join ... 
    join ... 
where ...; 

Oracle 可能决定在加入和过滤之前调用函数myFun,因此它将被称为100万次。由于上下文切换,从SQL调用PL/SQL函数的速度很慢。

当你把它包像这样:

select col1, col2, myFun(col3) 
    from (select col1, col2, col3 
      from aTable 
      join ... 
      join ... 
      where ... 
     ); 

...现在甲骨文可能要进行联接和过滤第一,获得10行回来,然后调用myFun 10倍。

如果每个函数调用需要0.001秒,那么这将花费百万* 0.001 = 1,000秒钟的第一查询,和10 * 0.001 = 0.01秒的第二包裹查询。

请注意,我说的可能可能 - 优化器可以做出不同的选择,这取决于统计数据 - 因此对于某些查询这两个版本可以调用该函数只有10倍,或两者称之为100万次。

此提示应确保第二个版本总是很快,告诉甲骨文没有这两个查询合并为一个:

select /*+ no_merge(v) */ col1, col2, myFun(col3) 
    from (select col1, col2, col3 
      from aTable 
      join ... 
      join ... 
      where ... 
     ) v; 
+0

我也应该这样做...也许在第一个版本的功能是适用于每一行,在第二个版本的功能是应用结果(用join/where表示)的行较少。谢谢! – Mistre83