多次调用函数与分配局部变量的性能

时间:2017-01-27 18:24:56

标签: oracle plsql

好奇,说我有这个Seeded Function FND_GLOBAL.USER_ID返回当前登录用户的User_ID,我有一个自定义包(下面)更新了一堆表(表dml和ddl在问题的结尾)。

一个程序只调用FND_GLOBAL.USER_ID并将其分配给一个局部变量,另一个程序调用{​​{1}}:

FND_GLOBAL.USER_ID

在单独的会话中,我运行下面的脚本以使用create or replace package call_pkg_var is procedure call_once (p_trx_no number); procedure call_multi (p_trx_no number); end call_pkg_var; / create or replace package body call_pkg_var is procedure call_once (p_trx_no number) is l_user_id number := fnd_global.user_id; begin update table_a set user_id = l_user_id where trx_no = p_trx_no; update table_b set user_id = l_user_id where trx_no = p_trx_no; update table_c set user_id = l_user_id where trx_no = p_trx_no; end call_once; procedure call_multi (p_trx_no number) is begin update table_a set user_id = FND_GLOBAL.USER_ID where trx_no = p_trx_no; update table_b set user_id = FND_GLOBAL.USER_ID where trx_no = p_trx_no; update table_c set user_id = FND_GLOBAL.USER_ID where trx_no = p_trx_no; end call_multi; end call_pkg_var; / 更新表格:

call_pkg_var.call_once

这个使用set timing on; begin for i in 1 .. 10000 loop call_pkg_var.call_once(i); end loop; commit; end;

call_pkg_var.call_multi

结果:

set timing on;
begin

  for i in 1 .. 10000 loop  
    call_pkg_var.call_multi(i);    
  end loop;

  commit;

end;

这是否会以某种方式说多次调用函数比仅将函数分配给变量更好? 如果没有,最好的方法是什么?

表DML和DDL

Run#    call_pkg_var.call_once
------- -----------------------
1       00:00:02.248
2       00:00:02.100
3       00:00:02.101
4       00:00:02.069
5       00:00:02.136
6       00:00:02.113
------  -------------
Average 00:00:02.128


Run#    call_pkg_var.call_multi
------- -----------------------
1       00:00:02.051
2       00:00:02.047
3       00:00:02.054
4       00:00:02.071
5       00:00:02.054
6       00:00:02.051
------  -------------
Average 00:00:02.055

2 个答案:

答案 0 :(得分:0)

我同意brian的观点。总是尝试在构建的函数中使用oracle来获得所需的输出。你可以使用sys_context来获取当前用户,而且我不确定是什么其他方法你正在使用。试着避免sql和pl / sql之间的切换上下文

答案 1 :(得分:0)

大多数人可能不知道的是FND_GLOBAL是Oracle Corporation作为其Oracle电子商务套件的一部分提供的软件包。

如果您查看该软件包的源代码,您会看到FND_GLOBAL已经在PL /中缓存了USER_ID,这是e-BS用户ID而不是Oracle数据库用户ID SQL变量。因此,您的“一次呼叫”和“多次呼叫”的工作量几乎完全相同。

我希望“call multi”仍在进行 little 更多的工作 - 如果你运行了很多测试并评估结果,你就能够检测到它统计学。

但是,如果您使用的是Oracle 12c,我不确定该版本是否删除了PL / SQL优化器只能内联调用同一程序单元中的函数的限制。如果启用PL / SQL警告,如果正在进行任何类型的内联,则应该收到警告。

供参考,以下是您的操作方法:

alter session set plsql_warnings='enable:all';

CREATE OR REPLACE PACKAGE...  << your package code >>

show errors;   -- Works in SQL*Plus, take your chances with other IDEs.