0

バックグラウンド

現在、DB2 V9 バージョンを使用しています。ストアド プロシージャの 1 つが実行に時間がかかっています。BMC apptune を調べたところ、以下の SQL が見つかりました。次のクエリを実行するために使用した 3 つのテーブルがあります。
ACCOUNT テーブルには 3413 のレコードがあります EXCHANGE_RATE には 1267K のレコードがあります BALANCE には 113M のレコードがあります

誰かが最近、次のコードをクエリに追加しました。このため、問題があったと思います。

AND (((A.ACT <> A.EW_ACT)             
      AND (A.EW_ACT <> ' ')                    
      AND (C.ACT = A.EW_ACT))         
     OR (C.ACT = A.ACT))                

クエリ

SELECT F1.CLO_LED                               
INTO :H :H  
FROM (SELECT A.ACT, A.BNK, A.ACT_TYPE,                                  
             CASE WHEN :H = A.CUY_TYPE THEN DEC(C.CLO_LED, 21, 2)                 
             ELSE DEC(MULTIPLY_ALT(C.CLO_LED, COALESCE(B.EXC_RATE, 0)), 21, 2)         
             END AS CLO_LED                           
      FROM ACCOUNT A                             
      LEFT OUTER JOIN EXCHANGE_RATE B                 
      ON B.EFF_DATE = CURRENT DATE - 1 DAY         
      AND B.CURCY_FROM  = A.CURNCY_TYPE       
      AND B.CURCY_TO = :H          
      AND B.STA_TYPE = 'A'                   
        , BALANCE C                           
      WHERE A.CUSR_ID = :DCL.CUST-ID   
      AND A.ACT = :DCL.ACT
      AND A.EIG_RTN = :WS-BNK-ID                  
      AND A.ACT_TYPE = :DCL.ACT-TYPE    
      AND A.ACT_CAT = :DCL.ACT-CAT 
      AND A.STA_TYPE = 'A'                      
      AND (((A.ACT <> A.EW_ACT)             
            AND (A.EW_ACT <> ' ')                    
            AND (C.ACT = A.EW_ACT))         
           OR (C.ACT = A.ACT))                
      AND C.BNK =  :WS-BNK-ID                
      AND C.ACT_TYPE = :DCL.ACT-TYPE  
      AND C.BUS_DATE = :WS-DATE-FROM) F1                                              
WITH UR 
4

1 に答える 1

2

このクエリでは、多くの奇妙なことが起こっています。その中で最も厄介なのは、明示的な結合と暗黙的な結合構文を混在させることです。率直に言って、システムがそれをどのように解釈するかはわかりません。また、入力と出力の両方に同じホスト変数を使用しているようです。しないでください。
また、列名が短いのはなぜですか? DB2 (少なくともそのバージョン) は、はるかに長い列名をサポートしています。できれば人々の正気を保ってください。

速度が遅い理由を完全に説明することはできません。アクセス プランを確認する必要があるかもしれません。それまでの間、より高速な形式 に再構築れたクエリを次に示します。

SELECT CASE WHEN :inputType = a.cuy_type THEN DEC(b.clo_led, 21, 2)
            ELSE DEC(MULTIPLY_ALT(b.clo_led, COALESCE(c.exc_rate, 0)), 21, 2) END
INTO :amount :amountIndicator  -- if you get results, do you need the indiciator?
FROM Account as a
JOIN Balance as b  -- This is assumed to not be a 'left', given coalesce not used
ON b.bnk = a.eig_rtn
AND b.act_type = a.act_type
AND b.bus_date = :ws-date-from
AND ((a.act <> a.ew_act     -- something feels wrong here, but
      AND a.ew_act <> ' '   -- without knowing the data, I don't
      AND c.act = a.ew_act) -- want to muck with it.
     OR c.act = a.act)
LEFT JOIN Exchange_Rate as c
ON c.eff_date = current_date - 1 day
AND c.curcy_from = a.curncy_type
AND c.sta_type = a.sta_type
AND c.curcy_to = :destinationCurrency
WHERE a.cusr_id = :dcl.cust-id
AND a.act = :dcl.act
AND a.eig_rtn = :ws-bnk-id
AND a.act_type = :dcl.act-type
AND a.act_cat = :dcl.act-cat
AND a.sta_type = 'A'
WITH UR
FECTCH FIRST 1 ROW ONLY

その他の注意事項:

  1. 必要な列のみを正確に指定します。特定の状況下では、これによりインデックスのみのアクセスが許可されますが、それ以外の場合は、フォローアップのテーブル アクセスが必要になる場合があります。ただし、これはおそらくここでは役に立ちません。
  2. COALESCE(c.exc_rate, 0)どういうわけか気分が悪い - 為替レートが存在しない場合、 の金額を0返します。ある種のインジケーターを返すか、外部結合ではなく通常の結合にする必要がある場合があります。

また、このバージョンと、場合によってはテーブル間の条件に加えてホスト変数が指定されているバージョンの両方を試してください。オプティマイザは値を自動的に変換できるはずですが、一部の条件下ではできない場合があります (実装の詳細)。

于 2012-04-18T16:40:21.297 に答える