0

明示カーソルからいくつかの行を更新する PL/SQL ブロックを実行しています。カーソルを宣言するコードは次のとおりです。

cursor DUP_SUBJECTS is  
  select * 
    from ODS_SUBJECT_D  
   WHERE SUBJECT_COD = ANY (SELECT SUBJECT_COD  
                              FROM ODS_SUBJECT_D  
                             WHERE END_DATE = TO_DATE ('31-12-9999','DD-MM-YYYY')   
                             GROUP BY SUBJECT_COD, ROW_TYPE_DE  
                            HAVING COUNT(*) > 1)  
   ORDER BY SUBJECT_COD, START_DATE; 

本体の最初のステートメントはDBMS_OUTPUT.PUT_LINE、ブロックの実行を開始するタイミングを通知するためのものです。上記のスクリプトのクエリは、テーブルの 2900000 行から 20000 行を返します。スクリプトの宣言ブロックで非常に長い時間がかかるようです (30 分経ってもメッセージはまだ出力されません)。
スクリプトのパフォーマンスを最適化するための提案はありますか?

ありがとう、
アントニオ

4

3 に答える 3

1

あなたは仕組みを誤解してDBMS_OUTPUTいます。DBMS_OUTPUTコード ブロック全体の実行が完了するまで、クライアントは に送信されたメッセージを受信できません。これは、メッセージにタイムスタンプを追加することで確認できDBMS_OUTPUTます。最初のメッセージはすぐに書き込まれ、実際のボトルネックは別の場所にあることがわかると思います。

于 2012-11-06T13:42:47.203 に答える
0

クエリの別の書き方を試すこともできます。

cursor dup_subjects is  
  select
    * 
  from (
    select
      o.*,
      count(*) over (partition by subject_cod, row_type_de) count_per
    from
      ods_subject_d
    where
      end_date = date '9999-12-31')
  where
    count_per > 1
  order by
    subject_cod,
    start_date;

end_date があまり一般的な値ではない場合は、必ずインデックスを作成してください。この値を除いて end_date を頻繁にクエリしない場合は、次のインデックスを作成することを検討してください。

create index ...
on     ods_subject_d (
         case end_date
           when date '9999-12-31' then 1
         end)

...そしてその述語を...に変更します

where case end_date when date '9999-12-31' then 1 end = 1

値の分布と "count(*) > 1" 条件を満たす可能性についての知識があれば、インデックス作成とクエリをさらに改良できる可能性があります。

于 2013-04-11T18:45:34.310 に答える