• ベストアンサー

PL/SQLのパフォーマンスについて

PL/SQLで、元のプログラムから、部品プログラム(以下のTEST_BUHIN)を呼ぶ際の、 パフォーマンスについてお聞きしたいことがあります。 Oracle8i環境を使っています。 以下の2つをコンパイルすると考えてください。 -------------------------------------------------- CREATE OR REPLACE TYPE test_type as object (  COL1 NUMBER(11),  COL2 VARCHAR2(20),    (実際には、40項目くらいあります)   ); / -------------------------------------------------- CREATE OR REPLACE PACKAGE BODY TEST_BUHIN AS  PROCEDURE TESTINSERT(TESTDATA IN test_type)  AS  BEGIN   INSERT INTO TESTTABLE VALUES(    TESTDATA.COL1,TESTDATA.COL2, ・・・    (以下略) -------------------------------------------------- 今、TESTTABLEにINSERTするプログラムを作成したいのですが、 パフォーマンスを最優先に考えたいと思っています。 その場合、元のプログラム内にINSERT文を作るべきか、 部品(TEST_BUHIN)を使用すべきか迷っています。 パフォーマンスがほぼ同じであれば、部品(TEST_BUHIN)を使用したいと思っています。 部品を使うとパフォーマンスが極端に落ちるということであれば、 部品はコンパイルせずに、元のプログラム内にINSERT文を作成しようと思います。 オブジェクトタイプ型変数を引数として渡した場合、 パフォーマンスへの影響はあるのでしょうか? 自分でも調べてみたのですが、いまいち分かりませんでした。 あと、大きな引数を渡した場合に、メモリをたくさん使ってしまうのかどうかも気になります。 文章が分かりづらいと思いますので、みなさんのご意見などを見て補足させていただきます。 Oracle、PL/SQLに詳しい方、よろしくお願いいたします。

  • Oracle
  • 回答数2
  • ありがとう数9

質問者が選んだベストアンサー

  • ベストアンサー
  • jmh
  • ベストアンサー率23% (71/304)
回答No.2

in は by reference だと思います。

cucsna
質問者

お礼

回答ありがとうございます。 確か、集約のSQLのときも回答いただいた方ですよね。 前回に引き続きありがとうございます。 回答を拝見した感じでは、アドレスを渡しているという感じなのでしょうか? だとすると、パラメータを渡すことで、特にパフォーマンスが落ちるとか、 メモリを余分に使うことはない、という印象を持ったのですが・・・ 知識が乏しいため、もう少し詳しい説明などいただけるとありがたいです。 よろしくお願いいたします。

cucsna
質問者

補足

お礼欄を使ってしまったので、こちらに書かせていただきます。 「by reference」という文字を頼りに探したところ、Oracleのリファレンスにたどり着くことができました。 英語が分からないので、知り合いに解読してもらって、理解しました。 割と急ぎだったのでとても助かりました。ありがとうございました。

その他の回答 (1)

回答No.1

inset文の埋め込みやストアド呼び出しの場合ですと、そんなにパフォーマンスは変わらない気がします。ただ、ストアドの場合ですと、共有プールに固定できるので若干速くなるのではと。 共有プールに固定する方法は [$ORA_HOME]\RDBMS\ADMIN\DBMSPOOL.SQLを流した後、 execute dbms_shared_pool.keep('[オーナ].TEST_BUHIN')を流せばできます。 これであればalter system flush shared_poolが実行されても開放されません。 >オブジェクトタイプ型変数を引数として渡した場合、 >パフォーマンスへの影響はあるのでしょうか? ごめんなさい。これはよくわかりません。たぶん、TYPEのサイズに比例するだけだとは思いますが...。 たいしたアドバイスでなくて申し訳ないです。

cucsna
質問者

お礼

ありがとうございました。 コーディングやコード内のロジックにしか目がいっていなかったのですが、パフォーマンスチューニングの方法をいろいろ調べるきっかけになりました。 ありがとうございました。

cucsna
質問者

補足

回答ありがとうございます。 呼び出し元のプログラムもストアドにするので、INSERT文のパフォーマンスは差がなさそうです。 >>オブジェクトタイプ型変数を引数として渡した場合、 >>パフォーマンスへの影響はあるのでしょうか? >ごめんなさい。これはよくわかりません。たぶん、TYPEの>サイズに比例するだけだとは思いますが...。 ということは、オブジェクトタイプのサイズが大きいと、 部品を呼び出す際のパフォーマンスが下がるということでしょうか? 引数を渡す際の、メモリとか、裏の動きが分からないので、さっぱり見当がついてないのですが・・・。 知識がないため、質問自体がグチャグチャですみません。 また何か気づかれましたら、よろしくお願いいたします。

関連するQ&A

  • [PL/SQL]REFCURSORが戻り値のプロシージャについて

    [PL/SQL]REFCURSORが戻り値のプロシージャについて お世話になってます タイトルの内容について、親プロシージャより引数を受け取り 子プロシージャでカーソルをオープンして、そのカーソルを親に戻す。 というプロシージャなのですが、親から実行した場合には問題ないのですが 子をSI ObjectBrowserから実行すると[実行][デバッグ]共に 押した瞬間に止まってしまいます。 下記にソースを記述します --カーソル変数の定義 CREATE OR REPLACE PACKAGE LC7BDEV.PKG_TEST_CURSOR IS  TYPE TEST_TYPE IS RECORD  (COL1 TABLE1.COL1%TYPE ,   COL2 TABLE1.COL2%TYPE ); TYPE CUR_TEST IS REF CURSOR RETURN TEST_TYPE; END; --親プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST  (   in_COL_KEY IN TABLE1.COL_KEY%TYPE  ) IS  TEST_REC  PKG_TEST_CURSOR.CUR_TEST;  TEMP_COL1 TABLE1.COL1%TYPE;  TEMP_COL2  TABLE1.COL1%TYPE; BEGIN  PD_TEST_KO(in_COL_KEY,TEST_REC);  loop   fetch TEST_REC into TEMP_COL1,TEMP_COL2;   exit when TEST_REC%notfound;   dbms_output.put_line(TEMP_COL1 || ',' || TEMP_COL2);  end loop;    close TEST_REC; END; --子プロシージャ CREATE OR REPLACE PROCEDURE PD_TEST_KO  (   in_COL_KEY  IN  TABLE1.COL_KEY%TYPE ,   in_TEST_REC OUT PKG_TEST_CURSOR.CUR_TEST ,  ) IS BEGIN  OPEN in_TEST_REC FOR   SELECT COL1,COL2   FROM TABLE1   WHERE COL_KEY = in_COL_KEY END;

  • PL/SQLの文法

    oracle8,windows95を使用しています。 PL/SQLで、シーケンスを削除して再度作成するという処理を書きたいのですが、PL/SQLはまったくの素人のためアドバイスをいただけたら、と思います。 実行したいのは、以下のSQL文です。 1) SQL>DROP SEQUENCE SQC_TEST 2) SQL>CREATE SEQUENCE SQC_TEST INCREMENT BY 1 START WITH 1 MAXVALUE 9999 MINVALUE 1 CYCLE; これを、PL/SQLで実行するにはどうかけばよいでしょうか? CREATE OR REPLACE PROCEDURE HC_CREATE_SEQ BEGIN DROP SEQUENCE SEQ_車両申請 FROM DUAL; CREATE SEQUENCE SQC_TEST INCREMENT BY 1 START WITH 1 MAXVALUE 9999 MINVALUE 1 CYCLE; END; / と書いてみましたがコンパイルに失敗しましたとおこられてしまいます。 ヒントだけでもいただけたら、と思います。 よろしくお願いいたします。

  • PL/SQLについて

    以下のVIEWをPROCEDURE内で使用しています。 CREATE OR REPLACE VIEW VW_KAIIN (CODE,NAME,TEL,STARTYMD) AS SELECT * FROM KAIIN WHERE STARTYMD <= TO_CHAR(SYSDATE,'YYYYMMDD') ※STARTYMDには有効な開始日付が入ります。 条件部分でSYSDATEではまずいことになり、 特定の日付を指定しなければならなくなりました。 VIEW自体にパラメータ渡しはできないということで、 CREATE OR REPLACE PROCEDURE TABLE_B_UPDATE (I_YYYY IN TABLE_A.YYYYY%TYPE, I_MM IN TABLE_A.MM%TYPE, I_DD IN TABLE_A.DD%TYPE,) PROCEDURE内でI_YYYY、I_MM、I_DDを条件に変更した VIEWを動的に作成して、処理をしたいのですが、 こういった事は可能でしょうか? そのまま書いてみましたが、CREATE部分でエラーが出てしまい、コンパイルできませんでした。 もし不可能である場合は、代替案をご教授いただけるとありがたいです。 どうかよろしくお願いします。

  • PL/SQLのエラー処理について

    PL/SQLを勉強し始めたのですが、テーブルを作成してから、データを流し込むという処理をしたいのですが、テーブルの作成に失敗しらたら、処理を終了させるという処理はできないのでしょうか? それとも、考え方が違うのでしょうか?アドバイスお願いします。 次のようにPL/SQLを作成しています。 例) declare curHandle1 INTEGER; begin curHandle1 := DBMS_SQL.OPEN_CURSOR; DBMS_SQL.PARSE(curHandle1, 'create table xxx as select * from xxx where ID=-1', DBMS_SQL.V7); DBMS_SQL.CLOSE_CURSOR(curHandle1); exception when OTHERS then エラーになったら、処理終了したい(次のブロックにいきたくない) end; declare begin      insert into xxx NOLOGGING values (1,'test'); end; よろしくお願いします。

  • PL/SQLでエラー

    PL/SQLの使用方法を検討しており、下記のようにサンプルを作成しました。 //1. 宣言部 create or replace package Pac is procedure Pro1(p1 in varchar2); end; / パッケージが作成されました //2. 本体 create or replace package body Pac is procedure Pro1(p1 in varchar2) is tempdate DATE; begin select to_char(sysdate, 'yyyy/mm/dd') INTO tempdate from dual; DBMS_OUTPUT.PUT_LINE('引数は' || p1 || 'です。'); DBMS_OUTPUT.PUT_LINE('日付は' || tempdate || 'です。'); end; end; / パッケージ本体が作成されました //3. 実行 execute Pac.Pro1('a'); // エラー内容 行1でエラーが発生しました。: ORA-00900: invalid SQL statement SQLPlusより、上記の[1. 宣言部]でパッケージを作成し、[2. 本体]で本体部分を作成しました。 その後、[3. 実行]を実施しましたが、 エラーが出力されて実行されません。 何がいけないのかお気づきの点がございましたら、 よろしくお願いします。

  • VB6でのPL/SQLの実行について

    現在VB6(SP6)でORACLEのデータベースに接続後、プロシージャを実行してOUTのパラメータを取得したいと思ってプログラムを作っております。 ORACLEへの接続はいろいろ調べてできたのですが、プロシージャの実行(呼び出し)のしかたがわからず困っております。 PL/SQL(プロシージャ名"TEST_DATA") out1 = TEST(OUTパラメータ1) out2 = これはテストです。(OUTパラメータ2) VB6(SP6) Dim OraSession As OraSession Dim OraDatabase As OraDatabase Dim OraDynaset As OraDynaset Dim P1 AS String Dim P2AS String '接続処理 Set OraSession = CreateObject("OracleInProcServer.XOraSession") Set OraDatabase = OraSession.OpenDatabase("TEST", "TEST/TEST DB_DEFAULT) OraSession.BeginTrans 'ここでPL/SQLを実行して、パラーメタを取得したいです。 '取得したパラメータをセット P1 = パラメータ1(TEST) P2 = パラメータ1(これはテストです。) OraSession.CommitTrans '結果表示 Call MsgBox(P1 & "結果" & P2) ご教授のほどをお願いいたします。

  • PL/SQLでCSVを作成又は、読み込みたい

    下記のエラーが出て、UTL_FILEパッケージが使用できません。なぜでしょう? 下記SQL文の「※1」箇所で「UTL_FILE」の後 「.」を入力しても、「FILE_TYPE」は選択肢には表示されず、やむを得ず手入力しました。 ~~~~~~~~~~~~~~~~~~~~~~~ 問題のSQL文 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECLARE  DNM VARCHAR2(200) := 'C:\TMP';  FNM VARCHAR2(200) := 'TEST.CSV';  CURSOR CUR1 IS      SELECT COL1, COL2, COL3, COL4, COL5     FROM A;  FHANDLE UTL_FILE.FILE_TYPE;  ←←←←←←←←←←  ※1  REC VARCHAR2(2000); BEGIN  FHANDLE := UTL_FILE.FOPEN(DNM,FNM,'W',2002);  UTL_FILE.PUTF(FHANDLE,'"%S","%S","%S","%S"\N','タイプ','オブジェクト','作成日','更新日');    BEGIN    FOR CUR_REC IN CUR1 LOOP    UTL_FILE.PUTF(FHANDLE,'"%S","%S","%S","%S"\N','タイプ','オブジェクト','作成日','更新日');   END LOOP;  END;  UTL_FILE.FCLOSE(FHANDLE); END; ~~~~~~~~~~~~~~  エラーメッセージ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Error [row:1,col:1] ORA-06510: PL/SQL: ユーザー定義の例外が発生しましたが、処理されませんでした ORA-06512: "SYS.UTL_FILE", 行120 ORA-06512: "SYS.UTL_FILE", 行293 ORA-06512: 行14

  • PL/SQLのエラーについて

    こんばんは。PL/SQLのエラーについて質問させて頂きます。 現在、Oracle8.1.7のデータベースを使用したオラクルのE-business Suiteという人事系システムで開発をしています。 そこで、SQL*Plusを使用してPL/SQLのパッケージをコンパイルしたところ、パッケージ仕様部も本体部もコンパイルのエラーは出なかったのですが、E-business SuiteにPL/SQLを設定し、動作させようとしたら、下記のようなエラーが発生しました。 -------------------------------------------------------------------- FDPSTP 内のOracleエラー 6550 原因: ORA-06550: 行 1、列 7: PLS-00221: 'ZT_TYOUHYOU_HENSEI_PKG'がプロシージャではないか、または未定義です。 ORA-06550: 行 1、列 7: PL/SQL: Statement ignored が原因で FDPSTP に失敗しました。 --------------------------------------------------------------------- また、作成したPL/SQLパッケージの仕様部は下記のとおりです。 -------------------------------------------------------------------- CREATE OR REPLACE PACKAGE APPS.ZT_TYOUHYOU_HENSEI_PKG AS FUNCTION get_henseihyo_kbn (i_grade IN VARCHAR2,o_hensei_kbn OUT VARCHAR2) RETURN NUMBER; <・・・・・中間部分は省略・・・・・> PROCEDURE main_shori (p_process_date IN VARCHAR2, p_location IN VARCHAR2); END ZT_TYOUHYOU_HENSEI_PKG; -------------------------------------------------------------------- 原因だと思われる心当たりの部分も探してみたのですが、このエラーの意味は何なのか、原因はどこにあるのか分かりません。 どなたかお判りの方、御回答よろしくお願い致します。

  • PL/pgSQLの使い方

    PL/pgSQLについて質問させてください。 以下のような2つのテーブルAとBがあります。 テーブルA: aid | fall0 | fall1 -----+-------+------- 001 | 0 | 0 002 | 0 | 0 テーブルB: bid | aid | fall --------+-----+------ 000001 | 001 | 0 000002 | 001 | 0 000003 | 002 | 0 000004 | 002 | 0 テーブルAとテーブルBの関係は1:nの関係です。 以下のような2つのことがやりたいです。 テーブルAのfall0,fall1,テーブルBのfallはフラグです。 今、テーブルBのaid=001であるすべての行のfallを0から1に変えたとき、 それに対応するテーブルAの行のfall1が0から1にかわる。またテーブルBのaid=001である少なくとも一つの行のfallを0から1に変えたとき、 それに対応するテーブルAの行のfall0が0から1にかわるようなプログラムを作りたいのですが、なかなかうまくいきません。今aid=001のときをやりましたが、aidは任意のときを想定しています。もし、ご存知の方がいらっしゃいましたら教えていただけないでしょうか? よろしくお願いいたします。以下は自分が書いたプログラムです。 drop table b; drop table a; create table A ( aid text primary key, fall0 integer, fall1 integer ); create table B ( bid text primary key, aid text not null references A(aid), fall integer ); insert into A values ('001',0,0); insert into A values ('002',0,0); insert into A values ('003',0,0); insert into B values ('000001','001',0); insert into B values ('000002','001',0); insert into B values ('000003','002',0); insert into B values ('000004','002',0); /* 関数の定義 */ create function tri_test() returns trigger as ' begin declare aid_rec if old.fall=0 and new.fall=1 then update a set fall1=1 where a.aid = select b.aid from b where b.fall = 1); end if; return new; end; ' language 'plpgsql'; /* トリガーの定義 */ create trigger tri_b after update or insert on b for each row execute procedure tri_test(); /* B テーブルへのデータ操作 */ update b set fall=1 where aid='001';

  • PL SQL のループ

    あるセレクト文のパフォーマンスを測定するためにループで複数回実行し時間を測定したいのですが、select 変数 into をしないとコンパイルできず実行できません。 同じセレクト文を複数回実行し時間を測定するのに良い方法は無いでしょうか? CREATE OR REPLACE PROCEDURE test IS BEGIN DBMS_OUTPUT.PUT_LINE(TO_CHAR(sysdate(),'YYYY/MM/DD HH24:MI:SS')); FOR i IN 1..100 LOOP SELECT a,b,c,d,e FROM tbl; END LOOP; DBMS_OUTPUT.PUT_LINE(TO_CHAR(sysdate(),'YYYY/MM/DD HH24:MI:SS')); END;