Oracle 11g - 使用大数据进行简单查询的速度很慢

时间:2015-01-14 14:18:54

标签: sql oracle oracle11g

我们有3张桌子

TB_ETD_NON_MKTS_TRANS_OP - 3000万条记录

TB_ETD_NON_MKTS_POS_OP - 3000万条记录

TB_ETD_ENUMERATION - 包含100条记录的主表

我们正在执行以下查询以仅获取20条记录

SELECT * FROM   (   SELECT 
    COUNT(*) OVER () CNT,
    ROW_NUMBER() OVER (ORDER BY REPORTING_TIMESTAMP DESC NULLS LAST) RN,
    INNER_QRY.*          FROM
    (SELECT MARRS_MSG_ID,
      OWN_OR_DEL_REP,
      ACTION,
      UTI_VALUE UTI,
      EN.DESCRIPTION REPORTING_PARTY,
      OP.REPORTING_PARTY REPORTING_PARTY_CODE,
      PRIMARY_ASSET_CLASS ASSET_CLASS,

      TRADE_PARTY_INTR INTERNAL_TRADE_REF_ID,
      TRANSACTION_REFERENCE_ID TRANSACTION_REFERENCE_ID,
      NAME_OF_TRADE_PARTY_1 COUNTERPARTY_NAME,
      ACTION INPUT_MESSAGE,
      REPORTING_TIMESTAMP REPORTING_TIMESTAMP,
      MSG_STATUS SDR_STATUS,
      COLL_PORTFOLIO_CODE_PARTY_1 COLL_PORTFOLIO_CODE,
      CORRECTION_STATUS CORRECTION_STATUS_CODE      
    FROM TB_ETD_NON_MKTS_TRANS_OP OP,
      TB_ETD_ENUMERATION EN
    WHERE OP.REPORTING_PARTY  = EN.NAME
    AND ( OWN_OR_DEL_REP NOT IN ('DD')
    OR OWN_OR_DEL_REP        IS NULL )
    AND REPORTING_PARTY IN
    (SELECT REGEXP_SUBSTR('HONGKONG,SINGAPORE,JERSEY','[^,]+', 1, LEVEL)
    FROM DUAL
      CONNECT BY REGEXP_SUBSTR('HONGKONG,SINGAPORE,JERSEY', '[^,]+', 1, LEVEL) IS NOT NULL
    )

    AND REPORTING_TIMESTAMP >= TO_DATE('11-JAN-2015','DD-MON-YYYY')
    AND REPORTING_TIMESTAMP <= TO_DATE('14-JAN-2015','DD-MON-YYYY')

    UNION ALL
    SELECT MARRS_MSG_ID,
      OWN_OR_DEL_REP,
      ACTION,
      UTI_VALUE UTI,
      EN.DESCRIPTION REPORTING_PARTY,
      OP.REPORTING_PARTY REPORTING_PARTY_CODE,
      PRIMARY_ASSET_CLASS ASSET_CLASS,      
      TRADE_PARTY_INTR INTERNAL_TRADE_REF_ID,
      TRANSACTION_REFERENCE_ID TRANSACTION_REFERENCE_ID,
      NAME_OF_TRADE_PARTY_1 COUNTERPARTY_NAME,
      LIFECYCLE_EVENT INPUT_MESSAGE,
      REPORTING_TIMESTAMP REPORTING_TIMESTAMP,
      MSG_STATUS SDR_STATUS,
      COLL_PORTFOLIO_CODE_PARTY_1 COLL_PORTFOLIO_CODE,
      CORRECTION_STATUS CORRECTION_STATUS_CODE      
    FROM TB_ETD_NON_MKTS_POS_OP OP,
      TB_ETD_ENUMERATION EN
    WHERE OP.REPORTING_PARTY  = EN.NAME
    AND ( OWN_OR_DEL_REP NOT IN ('DD')
    OR OWN_OR_DEL_REP        IS NULL )
    AND REPORTING_PARTY IN
    (SELECT REGEXP_SUBSTR('HONGKONG,SINGAPORE,JERSEY','[^,]+', 1, LEVEL)
    FROM DUAL
      CONNECT BY REGEXP_SUBSTR('HONGKONG,SINGAPORE,JERSEY', '[^,]+', 1, LEVEL) IS NOT NULL
    )    
    AND REPORTING_TIMESTAMP >= TO_DATE('11-JAN-2015','DD-MON-YYYY')
    AND REPORTING_TIMESTAMP <= TO_DATE('14-JAN-2015','DD-MON-YYYY')

    ) INNER_QRY   ) WHERE RN >= '1' AND RN   <= '20'

我们在REPORTING_TIMESTAMP上有索引

下面是执行计划,对我来说没问题,仍然只需要花费3分钟获取20条记录。

ExceutionPlan

1 个答案:

答案 0 :(得分:1)

以下是几个一般提示:

1)考虑重写这个表达式:

 AND REPORTING_PARTY IN
    (SELECT REGEXP_SUBSTR('HONGKONG,SINGAPORE,JERSEY','[^,]+', 1, LEVEL)
    FROM DUAL
      CONNECT BY REGEXP_SUBSTR('HONGKONG,SINGAPORE,JERSEY', '[^,]+', 1, LEVEL) IS NOT NULL
    )

如下:

 AND instr(','||:comma_separated_values||',', ','||REPORTING_PARTY||',') > 0

或在没有绑定的情况下:

 AND instr(',HONGKONG,SINGAPORE,JERSEY,', ','||REPORTING_PARTY||',') > 0

2)考虑更换

OWN_OR_DEL_REP NOT IN ('DD')
    OR OWN_OR_DEL_REP        IS NULL 

with:

NVL(OWN_OR_DEL_REP,'?') NOT IN ('DD') 

3)尝试摆脱嵌套循环(使用提示use_hash