0

実行時に定義されたテーブルからデータをフェッチし、実行時に定義された列に基づいてデータを取得する必要があります。現在、以下のように参照カーソルで動的SQLを使用しています。パフォーマンスを改善するためのより効率的な方法はありますか?

PROCEDURE check_error(p_table_name IN VARCHAR2
    ,p_keyword  IN VARCHAR2
    ,p_column_name IN VARCHAR2
    ,p_min_num IN NUMBER
    ,p_time_range IN NUMBER
    ,p_file_desc IN VARCHAR2
    )
IS  
   type t_crs is ref cursor;
   v_cur t_crs;

   v_file_name VARCHAR2(100);
   v_date_started DATE;
   v_date_completed DATE;
   v_counter NUMBER := 0;
   v_sql VARCHAR2(500);
   v_num NUMBER :=0;
BEGIN
   v_sql := 'SELECT '||p_column_name||', DATE_STARTED,DATE_COMPLETED FROM '||p_table_name
            || ' WHERE '||p_column_name||' LIKE '''||p_keyword||'%'' AND  DATE_STARTED > :TIME_LIMIT  ORDER BY '||p_column_name;

    OPEN v_cur FOR v_sql USING (sysdate - (p_time_range/1440));
    LOOP
        FETCH v_cur INTO v_file_name,v_date_started,v_date_completed;
        EXIT WHEN v_cur%NOTFOUND; 
        IF v_date_started IS NOT NULL AND v_date_completed IS NULL   
            AND (sysdate - v_date_started)*1440 > p_time_range THEN
                insert_record(co_alert_stuck,v_file_name,p_table_name,0,p_file_desc,p_time_range);               
        END IF;         
    END LOOP;
END;

ところで、これで良くなりますか?

v_sql := 'SELECT :COLUMN_NAME1, DATE_STARTED,DATE_COMPLETED FROM :TABLE WHERE :COLUMN_NAME2 LIKE :KEYWORD AND  DATE_STARTED > :TIME_LIMIT  ORDER BY :COLUMN_NAME3';

OPEN v_cur FOR v_sql USING p_column_name,p_table_name,p_column_name,p_keyword||'%',(sysdate - (p_time_range/1440)),p_column_name;
4

1 に答える 1

0

まず、コードが何をしているのかよくわかりません。あなたが投稿したコード(物事を単純化するために省略した可能性があります)では、IFステートメントは、節v_date_started IS NOT NULLがあるため、冗長であるかどうかをチェックします on 。列の節の単なる冗長な繰り返しであるかどうかをチェックします。そして、作成した動的 SQL ステートメントの追加句としてどちらが効率的かをチェックします。すべてのチェックを正確に 1 か所で実行することは理にかなっており、それらを実行する最も効率的な場所は SQL ステートメントです。WHEREDATE_STARTED(sysdate - v_date_started)*1440 > p_time_rangeWHEREDATE_STARTEDv_date_completed IS NULLWHERE

2 つ目は、このクエリで返される行の数と、どこで時間が費やされているかです。BULK COLLECTカーソルが多くの行を返す可能性がある場合 (多くの定義のために)、カーソルからコレクションを実行し、手順を変更してコレクションinsert_recordを受け入れて処理することで、少し効率が上がります。SQL ステートメントの実行にすべての時間が費やされ、クエリ自体がほんの一握りの行を返す場合、PL/SQL の一括操作によって効率が大幅に向上することはないでしょう。ボトルネックが SQL ステートメントの実行である場合は、渡されたテーブルに適切なインデックスが存在することを期待する必要があります。ボトルネックがinsert_recordプロシージャである場合は、そのプロシージャが何をコメントするかを知る必要があります。

第 3 に、insert_recordプロシージャが (少なくとも主に) フェッチしたデータを別のテーブルに挿入するだけの場合、すべてのループを取り除き、動的INSERTステートメントを生成するだけの方が効率的です。

第4に、編集に関して、テーブル名または列名にバインド変数を使用できないため、提案している構文は無効です。大量の構文エラーが生成されるため、より効率的ではありません。

于 2012-11-30T19:23:22.637 に答える