2012-04-18 79 views
0

背景

当前我正在使用DB2 V9版本。我的一个存储过程需要时间来执行。我查看了BMC apptune并找到了以下SQL。 我们用三个表来执行下面的查询。
ACCOUNT表3413个具有记录 EXCHANGE_RATE由具有 BALANCE是具有113M记录DB2 V9 ZOS - 性能调优

有人加入最近以下查询一段代码1267K记录。我想因为这个,我们遇到了问题。

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 

回答

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,否则可能是有效的数量。您可能需要返回某种指标,或将其作为普通连接,而不是外部连接。

另外,尝试这两种版本,并可能在那里主机变量除了表之间的条件指定一个版本。优化器应该能够自动通过这些值,但在某些条件下可能不会(实现细节)。