优化此查询超过追索权限

时间:2013-08-13 12:54:34

标签: sql database db2

SELECT DISTINCT                                  
    A.IDPRE                                   
    ,A.IDARTB                                  
    ,A.TIREGDAT                            
    ,B.IDDATE                                
    ,B.IDINFO                                
    ,C.TIINTRO                                 
FROM
    GLHAZQ  A                                 
    ,PRTINFO B                                 
    ,PRTCON  C                                 
WHERE
    B.IDARTB   = A.IDARTB                     
AND B.IDPRE    = A.IDPRE                      
AND C.IDPRE    = A.IDPRE                      
AND C.IDARTB   = A.IDARTB                     
AND C.TIINTRO  = (
    SELECT MIN(TIINTRO)          
    FROM
    PRTCON D              
    WHERE D.IDPRE = A.IDPRE  
    AND D.IDARTB  = A.IDARTB)
ORDER BY C.TIINTRO   

运行此查询(DB2)时出现以下错误

SQL0495N  Estimated processor cost of "000000012093" processor seconds   
("000575872000" service units) in cost category "A" exceeds a resource limit error  
threshold of "000007000005" service units.  SQLSTATE=57051

请帮我解决这个问题

2 个答案:

答案 0 :(得分:1)

显然,工作负载管理器正在阻止您使用太多资源。您需要调整查询,使其估算成本低于DBA设置的阈值。您将首先检查由db2exfmt生成的查询说明计划。如果需要帮助,请在此处发布计划以及表和索引定义。

要制作解释计划,请执行以下3个步骤:

  1. 执行db2 -tf $INSTANCE_HOME/sqllib/misc/EXPLAIN.DDL
  2. 创建说明表
  3. 通过执行explain语句生成计划:db2 explain plan for select ...<the rest of your query>
  4. 格式化计划:db2exfmt -d <your db name> -1(注意第二个参数是数字“1”,而不是字母“l”)。
  5. 要生成表DDL语句,请使用db2look实用程序:

    db2look -d <your db name> -o tables.sql -e -t GLHAZQ PRTINFO PRTCON
    

答案 1 :(得分:1)

虽然不是db2的人,但我怀疑查询语法是一样的。在您的查询中,您正在进行基于C.TIINTRO的子选择,这会导致性能下降。您也在查询所有记录。

我会通过预先查询MIN()值来启动查询,因为您甚至没有使用“C”别名中的任何其他值字段,所以请将其保留。

SELECT DISTINCT
      A.IDPRE,
      A.IDARTB,
      A.TIREGDAT,
      B.IDDATE,
      B.IDINFO,
      PreQuery.TIINTRO
   FROM
      ( SELECT D.IDPRE, 
               D.IDARTB, 
               MIN(D.TIINTRO) TIINTRO
           from 
              PRTCON D
           group by 
              D.IDPRE, 
              D.IDARTB ) PreQuery
         JOIN GLHAZQ  A
            ON PreQuery.IDPre = A.IDPRE
            AND PreQuery.IDArtB = A.IDArtB
         JOIN PRTINFO B
            ON PreQuery.IDPre = B.IDPRE
            AND PreQuery.IDArtB = B.IDArtB
   ORDER BY 
      PreQuery.TIINTRO

我会确保你有

索引
table      Index keys
PRTCON     (IDPRE, IDARTB, TIINTRO)
GLHAZQ     (IDPRE, IDARTB)
PRTINFO    (IDPRE, IDARTB)

如果你真的需要你的“C”表,你可以添加另一个JOIN,如

JOIN PRTCON C
  ON PreQuery.IDArtB = C.IDArtB
  AND PreQuery.TIIntro = C.TIIntro

有了这段时间,你可能会更好地拥有<覆盖索引“

GLHAZQ table key ( IDPRE, IDARTB, TIREGDAT )
PRTINFO    (IDPRE, IDARTB, IDDATE, IDINFO)

这样,索引包含您在查询中返回的所有元素,而不必返回所有实际的数据页面。它可以直接从索引中获取值