Oracle性能调优 - 列部分中的迭代表

时间:2017-05-15 08:22:56

标签: oracle performance optimization query-optimization

以下查询需要220秒。我想调整它。 查询中主要使用三个表。两个很大,一个相当小。

表中的计数:

INST        --14851330 records 
INST_S_INC  --52234424 records
INVES         -- 80000 records

查询:

SELECT 
(
  SELECT CODE
  FROM   CURRENCY CURR
  WHERE  CURR.CURRENCY_ID =
           ( SELECT CURRENCY_ID
             FROM INST  INSTR--14851330 records 
             WHERE INSTR.INVES_ID = INV.INVES_ID
             UNION ALL
             SELECT CURRENCY_ID
             FROM INST_S_INC ISI--52234424 records
             WHERE ISI.INVES_ID = INV.INVES_ID
           )
)
FROM   INVES INV -- 80000 records
WHERE  TRUNC(CREATED_DATETIME) <SYSDATE
ORDER BY CREATED_DATETIME
;--220 secs

我试图重写下面的查询,但它现在需要418秒。还有其他任何调整方法吗?

SELECT
(
  SELECT CODE
  FROM CURRENCY CURR
  WHERE CURR.CURRENCY_ID =ISI.currency_id
  union all
  SELECT CODE
  FROM CURRENCY CURR
  WHERE CURR.CURRENCY_ID =INSTR.currency_id
) code
FROM   INVES INV
       left outer join (
         select INVES_ID,currency_id from INST
       )  INSTR
       on  INSTR.INVES_ID = INV.INVES_ID
       left outer join (
         select INVES_ID,currency_id from INST_S_INC
       )  ISI
       on  ISI.INVES_ID = INV.INVES_ID
WHERE TRUNC(CREATED_DATETIME) <SYSDATE 
ORDER BY CREATED_DATETIME
;--418 secs

2 个答案:

答案 0 :(得分:0)

您可以更改:

TRUNC(CREATED_DATETIME) < SYSDATE

要:

CREATED_DATETIME < TRUNC( SYSDATE ) + INTERVAL '1' DAY

这将允许您使用CREATED_DATETIME上的任何索引(而不必在TRUNC(CREATED_DATETIME)上使用基于函数的索引。)

很难解释您的要求,因为您没有描述您要实现的目标或表结构,但您也可以尝试使用EXISTS并直接从CURRENCY表中选择:

SELECT curr.CODE
FROM   CURRENCY CURR
WHERE  EXISTS (
         SELECT CURRENCY_ID
         FROM   INST
                INNER JOIN
                INVES
                ON ( INST.INVES_ID = INVES.INVES_ID )
         WHERE  INSRT.CURRENCY_ID  = CURR.CURRENCY_ID
         AND    CREATED_DATETIME   < TRUNC( SYSDATE ) + INTERVAL '1' DAY
       )
OR     EXISTS (
         SELECT CURRENCY_ID
         FROM   INST_S_INC ISI
                INNER JOIN
                INVES
                ON ( ISI.INVES_ID = INVES.INVES_ID )
         WHERE  ISI.CURRENCY_ID   = CURR.CURRENCY_ID
         AND    CREATED_DATETIME  < TRUNC( SYSDATE ) + INTERVAL '1' DAY
       )

或者在UNION ALL内使用EXISTS

答案 1 :(得分:0)

WHERE  TRUNC(CREATED_DATETIME) <SYSDATE

这个过滤器有什么意义?假设您将来不创建基本上定义整个表扫描的记录。

在没有解释计划和数据量,倾斜等细节的情况下进行性能调整是一个杯子的游戏,但这是我的猜测:

SELECT curr,code
FROM   INVES INV
       left outer join INST
       on  INSTR.INVES_ID = INV.INVES_ID
       left outer join  INST_S_INCISI
       on  ISI.INVES_ID = INV.INVES_ID
left outer join CURRENCY CURR
on CURR.CURRENCY_ID = coalesce (ISI.currency_id, INST.currency_id)
ORDER BY inv.CREATED_DATETIME
;-