【问题标题】:Oracle 11g - Plain query with large data is performing slowOracle 11g - 大数据的普通查询执行缓慢
【发布时间】:2015-01-15 00:42:57
【问题描述】:

我们有 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 上有索引

下面是执行计划,在我看来还不错,仍然只获取 20 条记录,需要 3 分钟。

【问题讨论】:

  • 说明计划不完整。
  • 我无法附上执行计划图片
  • 在 SQL*Plus 中,生成格式正确的解释计划,使用代码标签复制粘贴。
  • 运行命令:EXPLAIN PLAN FOR your_query,然后运行SELECT * FROM table(DBMS_XPLAN.DISPLAY);,将结果复制并粘贴为文本。
  • 对查询运行 trace/tkprof 以查看时间等。

标签: sql oracle oracle11g


【解决方案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 

与:

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

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

【讨论】:

  • 谢谢,我试试这个
猜你喜欢
  • 2014-10-20
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
  • 2020-04-23
  • 2018-07-19
相关资源
最近更新 更多