0
CREATE OR REPLACE PROCEDURE UPDATE_CRDT_JV IS
 BEGIN
   UPDATE GL_DISTRIBUTION
         SET GL_DATE = (SELECT ADJ_DATE FROM ADJUSTMENTS WHERE
         ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
   WHERE TR_TYPE = 'ADJST';
   UPDATE GL_DISTRIBUTION 
         SET GL_DATE = (SELECT PARTY_ADJ_DATE FROM PARTY_ADJUSTMENT
         WHERE PARTY_ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
   WHERE TR_TYPE = 'PRTAJ';
   UPDATE GL_DISTRIBUTION
         SET GL_DATE = (SELECT VEN_PAY_VOU_DATE FROM PAYMENTS_TO_VENDORS WHERE
         VEN_PAY_VOU_NUMBER = TO_NUMBER(TR_NUMBER))
   WHERE TR_TYPE = 'CRPAY';
   UPDATE GL_DISTRIBUTION
         SET GL_DATE = (SELECT CHEQUE_DATE FROM SYS_PAYMENTS_HEADER WHERE
         REF_NUMBER = TO_NUMBER(TR_NUMBER))
   WHERE TR_TYPE = 'SYSPY';
   UPDATE GL_DISTRIBUTION
         SET GL_DATE = (SELECT POSTED_DATE FROM PURCHASE_INVOICE_HEADER WHERE
         POSTED_DATE IS NOT NULL AND PIV_NUMBER = TO_NUMBER(TR_NUMBER))
   WHERE TR_TYPE = 'CRINV';
   UPDATE GL_dISTRIBUTION
     SET GL_dATE = (SELECT DOC_dATE FROM REVERSE_HISTORY
           WHERE TR_NUMBER = TO_NUMBER(GL_DISTRIBUTION.TR_NUMBER)
         AND DOC_dATE IS NOT NULL AND TR_TYPE IN ('SYSPY','CRPAY'))
         WHERE TR_TYPE IN ('RSYSPY','RCRPAY');
   commit;
   UPDATE_INV_DET;
 END;

データベースの更新に15分以上かかっています。現在、SQLPLUSで次のクエリを使用してこれを更新しています。

EXECUTE UPDATE_CRDT_JV;

誰かがこの問題の解決策を知っているなら、plsは私を助けます

4

3 に答える 3

4

コードがどこで時間を費やしているかを把握するために、既に与えられたアドバイスに同意します。ただし、あなたのケースは非常に一般的であり、私はこの状況を認識していると思います.そのタイプのGL_DISTRIBUTIONのすべての行に対して他のテーブルがアクセスされるように更新ステートメントをコーディングしました.

解決策は、更新ステートメントを書き直すことです。これを効率的に行うには、次の 2 つの可能性があります。

1) 選択ステートメントを更新します (UPDATE (SELECT ...) SET ... WHERE ...)。これには、いくつかの一意のキー制約を設定するか、BYPASS_UJVC ヒントを使用する必要があります。

2) MERGE ステートメントを使用します。

以下に、単一のマージ ステートメントを使用してコードを書き直す方法の例を示します。GL_DISTRIBUTION テーブルのすべての行ではなく、テーブルごとに 1 つの外部結合を使用して、他のテーブルへのアクセスが 1 回行われるようになったため、パフォーマンスが大幅に向上することが期待されます。

例。テストデータ:

SQL> create table gl_distribution (tr_number, tr_type, gl_date)
  2  as
  3  select '1', 'ADJST', date '2011-01-01' from dual union all
  4  select '2', 'ADJST', null from dual union all
  5  select '3', 'PRTAJ', date '2011-01-01' from dual union all
  6  select '4', 'SYSPY', date '2011-01-01' from dual union all
  7  select '5', 'RCRPAY', date '2011-01-01' from dual
  8  /

Table created.

SQL> create table adjustments (adj_number, adj_date)
  2  as
  3  select 1, sysdate from dual union all
  4  select 2, sysdate from dual
  5  /

Table created.

SQL> create table party_adjustment (party_adj_number, party_adj_date)
  2  as
  3  select 3, sysdate from dual union all
  4  select 33, sysdate from dual
  5  /

Table created.

SQL> create table payments_to_vendors (ven_pay_vou_number, ven_pay_vou_date)
  2  as
  3  select 34, sysdate from dual
  4  /

Table created.

SQL> create table sys_payments_header (ref_number,cheque_date)
  2  as
  3  select 4, sysdate from dual
  4  /

Table created.

SQL> create table purchase_invoice_header (piv_number,posted_date)
  2  as
  3  select 35, sysdate from dual
  4  /

Table created.

SQL> create table reverse_history (tr_number,doc_date,tr_type)
  2  as
  3  select 5, sysdate, 'CRPAY' from dual
  4  /

Table created.
SQL>

あなたの手順(比較用):

SQL> CREATE OR REPLACE PROCEDURE UPDATE_CRDT_JV
  2  IS
  3  BEGIN
  4    UPDATE GL_DISTRIBUTION
  5    SET GL_DATE = (SELECT ADJ_DATE FROM ADJUSTMENTS WHERE  ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
  6    WHERE TR_TYPE = 'ADJST'
  7    ;
  8    UPDATE GL_DISTRIBUTION
  9    SET GL_DATE = (SELECT PARTY_ADJ_DATE FROM PARTY_ADJUSTMENT
 10    WHERE PARTY_ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
 11    WHERE TR_TYPE = 'PRTAJ'
 12    ;
 13    UPDATE GL_DISTRIBUTION
 14    SET GL_DATE = (SELECT VEN_PAY_VOU_DATE FROM PAYMENTS_TO_VENDORS
 15    WHERE VEN_PAY_VOU_NUMBER = TO_NUMBER(TR_NUMBER))
 16    WHERE TR_TYPE = 'CRPAY'
 17    ;
 18    UPDATE GL_DISTRIBUTION
 19    SET GL_DATE = (SELECT CHEQUE_DATE FROM SYS_PAYMENTS_HEADER WHERE
 20    REF_NUMBER = TO_NUMBER(TR_NUMBER))
 21    WHERE TR_TYPE = 'SYSPY'
 22    ;
 23    UPDATE GL_DISTRIBUTION
 24    SET GL_DATE = (SELECT POSTED_DATE FROM PURCHASE_INVOICE_HEADER WHERE
 25    POSTED_DATE IS NOT NULL AND PIV_NUMBER = TO_NUMBER(TR_NUMBER))
 26    WHERE TR_TYPE = 'CRINV'
 27    ;
 28    UPDATE GL_dISTRIBUTION
 29    SET GL_dATE = (SELECT DOC_dATE FROM REVERSE_HISTORY
 30    WHERE TR_NUMBER = TO_NUMBER(GL_DISTRIBUTION.TR_NUMBER)
 31    AND DOC_dATE IS NOT NULL AND TR_TYPE IN ('SYSPY','CRPAY'))
 32    WHERE TR_TYPE IN ('RSYSPY','RCRPAY')
 33    ;
 34    --commit;
 35    --UPDATE_INV_DET;
 36  END;
 37  /

Procedure created.

SQL>

私のおすすめ:

SQL> create procedure new_update_crdt_jv
  2  as
  3  begin
  4    merge into gl_distribution d
  5    using ( select to_number(d.tr_number) tr_number
  6                 , coalesce
  7                   ( a.adj_date
  8                   , pa.party_adj_date
  9                   , pv.ven_pay_vou_date
 10                   , sph.cheque_date
 11                   , pih.posted_date
 12                   , rh.doc_date
 13                   ) new_date
 14              from gl_distribution d
 15                   left outer join adjustments a
 16                     on to_number(d.tr_number) = a.adj_number
 17                     and d.tr_type = 'ADJST'
 18                   left outer join party_adjustment pa
 19                     on to_number(d.tr_number) = pa.party_adj_number
 20                     and d.tr_type = 'PRTAJ'
 21                   left outer join payments_to_vendors pv
 22                     on to_number(d.tr_number) = pv.ven_pay_vou_number
 23                     and d.tr_type = 'CRPAY'
 24                   left outer join sys_payments_header sph
 25                     on to_number(d.tr_number) = sph.ref_number
 26                     and d.tr_type = 'SYSPY'
 27                   left outer join purchase_invoice_header pih
 28                     on to_number(d.tr_number) = pih.piv_number
 29                     and d.tr_type = 'CRINV'
 30                   left outer join reverse_history rh
 31                     on to_number(d.tr_number) = rh.tr_number
 32                     and rh.tr_type in ('SYSPY','CRPAY')
 33                     and d.tr_type in ('RSYSPY','RCRPAY')
 34          ) n
 35       on ( d.tr_number = n.tr_number)
 36     when matched then
 37          update set d.gl_date = n.new_date
 38    ;
 39  end new_update_crdt_jv;
 40  /

Procedure created.

SQL>

手順を実行しましょう:

SQL> select * from gl_distribution
  2  /

T TR_TYP GL_DATE
- ------ -------------------
1 ADJST  01-01-2011 00:00:00
2 ADJST
3 PRTAJ  01-01-2011 00:00:00
4 SYSPY  01-01-2011 00:00:00
5 RCRPAY 01-01-2011 00:00:00

5 rows selected.

SQL> exec update_crdt_jv

PL/SQL procedure successfully completed.

SQL> select * from gl_distribution
  2  /

T TR_TYP GL_DATE
- ------ -------------------
1 ADJST  31-03-2011 14:41:19
2 ADJST  31-03-2011 14:41:19
3 PRTAJ  31-03-2011 14:41:19
4 SYSPY  31-03-2011 14:41:19
5 RCRPAY 31-03-2011 14:41:19

5 rows selected.

SQL> rollback
  2  /

Rollback complete.

SQL>

私の手順は同じ結果を返します:

SQL> exec new_update_crdt_jv

PL/SQL procedure successfully completed.

SQL> select * from gl_distribution
  2  /

T TR_TYP GL_DATE
- ------ -------------------
1 ADJST  31-03-2011 14:41:19
2 ADJST  31-03-2011 14:41:19
3 PRTAJ  31-03-2011 14:41:19
4 SYSPY  31-03-2011 14:41:19
5 RCRPAY 31-03-2011 14:41:19

5 rows selected.

お役に立てれば。

よろしく、
ロブ。

于 2011-03-31T12:51:23.007 に答える
3

この問題の解決策は次のとおりです。

  1. コードが時間を費やしている場所を把握する (つまり、プロファイルする)
  2. 最も遅い部分を高速化する方法を考え出す
  3. パフォーマンスが許容できるまで繰り返す

当て推量を好む場合は、次のいずれかを試してください。

複数の UPDATE を 1 つの UPDATE ステートメントに結合します。たとえば、@Aklopper で示されているように CASE 条件を使用します。

UPDATE の代わりに MERGE を使用して、相関サブクエリを回避します。良いかもしれないし、そうでないかもしれません。

示されている手順の最後に呼び出される UPDATE_INV_DET 手順を調べます。

于 2011-03-31T12:10:38.003 に答える
2

私は SQL Server 環境から来ましたが、このような CASE UPDATE ステートメントも役に立ちません (SQL での UPDATE CASE ステートメントの使用例 (Oracle に同等のメソッドがあるかどうかはわかりません) :

   UPDATE titles
           SET GL_DATE=
                     CASE
                       WHEN TR_TYPE = 'ADJST' THEN (SELECT ADJ_DATE FROM ADJUSTMENTS WHERE ADJ_NUMBER = TO_NUMBER(TR_NUMBER) END
                       WHEN TR_TYPE = 'PRTAJ'' THEN (SELECT PARTY_ADJ_DATE FROM PARTY_ADJUSTMENT
         WHERE PARTY_ADJ_NUMBER = TO_NUMBER(TR_NUMBER))
 END
                       ELSE price
                     END
于 2011-03-31T11:38:47.713 に答える