首页 文章

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

提问于
浏览
0

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

一个过程对 FND_GLOBAL.USER_ID 进行一次调用并将其分配给局部变量,另一个过程对 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;

结果:

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

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

Table DML and DDLs

create table table_a
(
  user_id number,
  trx_no  number
);  

create table table_b
(
  user_id number,
  trx_no  number
);  

create table table_c
(
  user_id number,
  trx_no  number
);  

insert into table_a (trx_no, user_id) values (1, null);
insert into table_b (trx_no, user_id) values (1, null);
insert into table_c (trx_no, user_id) values (1, null);

2 回答

  • 0

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

  • 0

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

    如果您查看该软件包的源代码,您将看到 FND_GLOBAL 已在PL / SQL变量中缓存 USER_ID ,即e-BS用户ID而非Oracle数据库用户ID . 所以,你的"call once"和"call multi"的工作量几乎完全相同 .

    我希望"call multi"仍然可以做更多的工作 - 并且如果你进行了大量的测试并且在统计上评估了结果,你就能够发现它 .

    但是,如果您使用的是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.
    

相关问题