2017-01-27 27 views
0

ちょうど不思議なことに、現在シードされている関数FND_GLOBAL.USER_IDが、現在ログインしているユーザーのUser_IDを返していて、束を更新するカスタムパッケージ(質問の終わりに表dmlとddl)。関数を複数回呼び出してローカル変数に代入したときの結果

1つの手順が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を使用して、この1:

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 

が、これは何とか機能を複数回呼び出すことがちょうどそれを変数に割り当てるよりも優れていると言うことでしょうか? そうでない場合は、どのような方法が最適ですか?私は、現在のユーザーを取得するためSYS_CONTEXTを使用することができブライアンのpoint.Alwaysが希望outputs.Youを取得するために、オラクルの組み込み関数での使用を試みる同意し、私はありません

表のDMLとDDLの

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);  
+1

コール10000回ループ内でこれらの手順や平均時間を比較します。この測定を3〜5回繰り返す。次に、この評価の結果を質問に追加してください。 – krokodilko

+0

ループを追加してテストを6回実行しました。複数の呼び出しがまだより速いようです。思考? @krokodilko –

+0

あなたは質問から最初のテストの結果を削除しました。私が覚えているように、1回の呼び出しで約90msの差があったのは約200msと300ms(ms =ミリ秒)でした。 2回目のテスト - 2秒間128ミリ秒2秒55ミリ秒 - 差は10000秒で88ミリ秒です。はい、それは絶対に速く、1回の呼び出しにつき約8,8マイクロ秒(数CPUサイクル)ですが、これは非常に衝撃的な業績です。 – krokodilko

答えて

0

他のどの方法を使用しているかを確認してください.SQLとpl/sqlの間のスイッチのコンテキストを避けるためにお試しください

+1

パッケージ 'FND_GLOBAL.USER_ID'が' SYS_CONTEXT'で検索可能なものに関連するものを返すと考える理由はありません。これは、データベース・ユーザーIDとは関係のないアプリケーション固有のユーザーIDである可能性があります。 –

+0

Matthewのように@ jayaprakash-nagarajanが述べたように、 'FND_GLOBAL.USER_ID'はOracle EBSのアプリケーション固有の機能ですが、私はその概念サンプルを私の質問に使用しました。ユーザーを得ることは私の質問の焦点では​​なく、むしろ関数を複数回呼び出すことと、それを一度呼び出すことと変数に割り当てることとの間のパフォーマンスでした。 –

0

FND_GLOBALは、Oracle e-ビジネススイート。

このパッケージのソース・コードを確認すると、FND_GLOBALは、PL/SQL変数に、Oracle DatabaseユーザーIDではないe-BSユーザーIDであるUSER_IDがすでにキャッシュされていることがわかります。だから、あなたの「一度電話」と「複数電話」はほぼ同じ量の仕事をしています。

私は "コールマルチ"はまだ少しより多くの仕事をしていることを期待しています - そして、あなたは多くのテストを実行し、結果を統計的に評価すればそれを検出することができます。

ただし、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. 
+0

私は11グラムですが、私はインラインに興味があります。編集してそれらのサンプルを与えることはできますか?ありがとう! –

関連する問題