2009-11-17 71 views
2

性能运行查询时,下面我遇到的DB2 9.1版本非常奇怪的表现:奇WHERE NOT EXISTS在DB2

select a.CYCL_NUM 
, a.AC_NUM 
, a.AUTHS_DTE 
, a.PL_ID 
, a.APRVD_RSPN_CDE 
, a.AUTHS_AMT 
, a.AUTHS_STS_CDE 
, a.TRAN_CTGR_CDE 
, a.MRCHN_CTGR_CDE 
, d.out_pu_au_amt 
from nwhd12.chldr_auths a, nwhd12.w_chldr_ac d 
where cycl_num = 200911 
and a.ac_num = d.ac_num 
and APRVD_RSPN_CDE = 'APV' 
and not exists (
    select 1 from auths_rev_hist b 
where a.cycl_num = b.cycl_num 
     and a.auths_dte = b.auths_dte 
     and a.TRAN_CTGR_CDE = b.TRAN_CTGR_CDE 
     and a.PL_ID = b.pl_id 
     and a.APRVD_RSPN_CDE = b.APRVD_RSPN_CDE 
and a.AUTHS_AMT = b.auths_amt 
     and a.TRAN_CTGR_CDE = b.TRAN_CTGR_CDE 
     and a.MRCHN_CTGR_CDE = MRCHN_CTGR_CDE 
) 
; 

什么是应该发生的是,查询访问nwhd12.chldr_auths的partion 97,因为这是与循环200911相对应的分区。相反,在访问分区97之后,它开始访问nwhd12.chldr_auths中的每个其他分区。现在,我被告知这是因为“WHERE NOT EXISTS”,但是这个语句中的循环仍然存在限制(a.cycl_num = b.cycl_num),所以为什么要扫描所有分区?

如果我在不存在的地方硬编码循环,那么查询按预期执行。

谢谢, 戴夫

回答

2

如果规划者是这样的容易混淆的,你需要尝试一些不同的配方。这未经测试(我甚至没有DB2,但CTE起源于那里):

WITH hist AS (
    cycl_num 
    , ac_num 
    , auths_dte 
    , pl_id 
    , aprvd_rspn_cde 
    , auths_amt 
    , auths_sts_cde 
    , tran_ctgr_cde 
    , mrchn_ctgr_cde 
    FROM auths_rev_hist b 
) 
, auths AS (
    SELECT 
    cycl_num 
    , ac_num 
    , auths_dte 
    , pl_id 
    , aprvd_rspn_cde 
    , auths_amt 
    , auths_sts_cde 
    , tran_ctgr_cde 
    , mrchn_ctgr_cde 
    FROM nwhd12.chldr_auths 
    WHERE cycl_num = 200911 
    AND aprvd_rspn_cde = 'APV' 
    EXCEPT 
    SELECT ... FROM hist 
) 
SELECT a.*, d.out_pu_au_amt 
FROM auths a, nwhd12.w_chldr_ac d 
WHERE a.ac_num = d.ac_num 
+0

有趣的是,我从来没有写过这种格式的查询。现在试试看,但似乎有一些错误,会看看我能否弄清楚。听起来就像计划者感到困惑!我是否认为加入不存在的地方应该像设计师那样表现? – CallCthulhu 2009-11-17 05:42:29

+0

WITH WITH引入了CTE(通用表格表达式),就像临时视图。你得到什么错误?关于混淆: 关于这个混淆:规划者实际上是正确的,而我却感到困惑:在SQL中,A AND B与B AND A完全相同(与大多数带短路的编程语言相反)。 – 2009-11-17 05:55:52