如何在Oracle临时表上使用DML而不生成大量撤消日志

时间:2010-03-12 04:20:29

标签: oracle plsql

使用Oracle临时表不会生成大量重做日志作为普通表。但是,仍会生成撤消日志。因此,如何在临时表上编写插入,更新或删除语句,但Oracle不会生成撤消日志或尽可能少地生成?

此外,在insert语句中使用/ + append /将生成很少的撤消日志。我对么?如果没有,有人可以解释我使用提示/ +追加 /?

INSERT /*+APPEND*/ INTO table1(...) VALUES(...);

3 个答案:

答案 0 :(得分:12)

Oracle需要UNDO信息来回滚事务中的DML。正如加里在评论中所说:

  

“UNDO需要回滚   如果是单一陈述的影响   中途失败。也是   需要提供ROLLBACK TO   SAVEPOINT或ROLLBACK(虽然是   全球临时表格后者   只会与会议有关   持续时间GTT)。“

此UNDO信息本身会产生REDO。对于这种情况你无能为力:临时表需要UNDO,这就是它的结束。

最小化UNDO的数量非常简单:只需插入记录并选择记录。 INSERT生成最小量的UNDO,因为回滚INSERT只需要rowid。相反,DELETE语句生成最多的UNDO,因为数据库必须存储整个记录。基本上,要回滚INSERT问题DELETE,要回滚DELETE问题INSERT。 UPDATE生成可变数量的UNDO,因为我们需要更改列的旧版本;更改的列越多,它们越大,UNDO生成的数量就越大。

<强>示范

在会话一中,用户会将大量记录插入临时表中,然后将其删除。在第二场会议中,DBA将监控事务的UNDO使用情况。

SSN1> insert into gtt23
  2      select * from big_table
  3  /

553928 rows created.

SSN1>

撤消使用:

SSN2> select space, noundo, used_ublk, used_urec from v$transaction
   2  /

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO         257      10816

SSN2>

现在删除:

SSN1> delete from gtt23
   2  /

553928 rows deleted.

SSN1>

撤消使用(长时间运行的语句中的几个样本)::

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO       11123     435605

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO       13413     525452

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO       14552     570567

SSN2>

提交(临时表具有事务范围,即DELETE ROWS)

SSN1> commit
   2  /

Commit complete.

SSN1>

撤消使用:

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

no rows selected

SSN2>

撤消用法是累积

SSN1> insert into gtt23
   2      select * from big_table
   3  /

553928 rows created.

SSN1> delete from gtt23
   2  /

553928 rows deleted.

SSN1> insert into gtt23
   2      select * from big_table
   3  /

553928 rows created.

SSN1>

撤消使用

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO         258      10816

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO       14766     579495

SSN2> r
   1* select space, noundo, used_ublk, used_urec from v$transaction

SPA NOU  USED_UBLK  USED_UREC
--- --- ---------- ----------
NO  NO       14819     581685

SSN2>

<强>摘要

因此,要最小化临时表生成的UNDO的影响,请确保插入一次正确的数据。避免对其应用更新,尤其要避免从中删除大量记录。如果您使用的是具有事务范围的临时表,则实际上不需要从中删除记录。如果您的临时表具有会话持续时间并且您需要清除它,那么最好使用TRUNCATE(如果可能),而不是DELETE。

答案 1 :(得分:2)

AskTom上找到了这个:

  

传统路径插入生成   UNDO。他们必须,你需要   能够回滚,你需要能够   支持多版本化。

     

UNDO始终受重做保护。

     

如果你指导全球的路径   临时表(插入/ * + APPEND   * /)您可以绕过表上的撤消 - 但不能绕过索引。因此,你可以减少(通常是因为它   通常是生成的索引   大多数撤消)重做的数量,但你   不能消除它。

答案 2 :(得分:-1)

我相信您也可以从NOLOGGING关键字获得一些好处。

附加提示表明Oracle应该使用DIRECT-PATH操作,这可以导致更快的插入。如果我没记错的话,您应该可以独家访问该表。插入后提交很重要,这样您就可以从中选择信息。