0

背景

目前我使用的是 DB2 V9 版本。我的一个存储过程需要时间来执行。我查看了 BMC apptune 并找到了以下 SQL。我们使用三个表来执行以下查询。
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 回答