0

Oracle グローバル一時テーブルのセーブポイントはすべてのデータを削除すると読みましたが、Oracle 11g でテストしたところ、ヒープ テーブルのように機能しました。誰でも説明できますか?

insert into table_1 values('one');
insert into table_1 values('two');
savepoint f1;
insert into table_1 values('three');
insert into table_1 values('four');

rollback to f1;

-- the records in table are 2 records just like heap tables, but I read that
-- savepoints in GTT truncates all the data
4

2 に答える 2

0

これどこで読んだ?Oracle SQLリファレンスにはないと思います。したがって、説明は簡単です。その主張の著者は、グローバル一時テーブルの動作をテストしていません。それか、DerbyDB などの他の SQL 実装の説明を読んでいたかのどちらかです。

完全を期すために、トランザクションまたはセッション スコープの役割を除外しましょう。2 つのグローバル一時テーブルを次に示します。

create global temporary table gtt1
   ( col1 varchar2(30) )
   ON COMMIT PRESERVE ROWS 
/

create global temporary table gtt2
   ( col1 varchar2(30) )
   ON COMMIT DELETE ROWS 
/

セッション スコープの実験を実行してみましょう。

SQL> insert into gtt1 values('one');

1 row created.

SQL> insert into gtt1 values('two');

1 row created.

SQL> savepoint f1;

Savepoint created.

SQL> insert into gtt1 values('three');

1 row created.

SQL> insert into gtt1 values('four');

1 row created.

SQL> rollback to f1;

Rollback complete.

SQL> select * from gtt1;

COL1
------------------------------
one
two

SQL> 

トランザクション スコープを持つテーブルの同じ結果:

SQL> insert into gtt2 values('five');

1 row created.

SQL> insert into gtt2 values('six');

1 row created.

SQL> savepoint f2;

Savepoint created.

SQL> insert into gtt2 values('seven');

1 row created.

SQL> insert into gtt2 values('eight');

1 row created.

SQL> rollback to f2;

Rollback complete.

SQL> select * from gtt2;

COL1
------------------------------
five
six

SQL>

実際、これは驚くべきことではありません。Oracleの公式ドキュメントには次のように記載されています。

「一時テーブルの定義は、通常のテーブルの定義と同じ方法で保持されます」

基本的にそれらヒープテーブルです。違いは次のとおりです。

  • データの範囲 (可視性)
  • データを永続化するために使用されるテーブルスペース (グローバル一時テーブルは一時テーブルスペースに書き込みます)。
于 2015-05-13T05:10:52.363 に答える
0

誤解していると思います-セーブポイントにロールバックすると、Oracleはセーブポイントの後に行われたすべての作業を元に戻す必要があります(セーブポイントの前に行われたコミットされていない作業は引き続き保持されます)。

一時テーブルの場合、Oracle はストレージ (セッションの一時セグメント) を遅延して割り当てます (セッションの一時セグメント)。通常のテーブルを TRUNCATE した場合のように、行を個別に削除するのではなく、単にストレージの割り当てを解除できます。

データが入力される前にセーブポイントがあり、そのセーブポイントにロールバックした場合にどうなるかを知りたいと思っていました.Oracleはストレージの割り当てを解除しますか、それともストレージを保持してその中の行を削除しますか?

前者であることが判明しました-切り捨てのように動作します。

SAVEPOINT f0;
SELECT * FROM v$tempseg_usage; -- Should show nothing for your session
insert into table_1 values('one');
insert into table_1 values('two');
SELECT * FROM v$tempseg_usage; -- Should show a DATA row for your session
savepoint f1;
insert into table_1 values('three');
insert into table_1 values('four');
rollback to f1; -- Undo three and four but preserve one and two
SELECT * FROM v$tempseg_usage; -- Still shows a DATA row for your session
rollback to f0; -- Undo all the inserts
SELECT * FROM v$tempseg_usage; -- row for your session has gone

これが重要な理由は、切り捨てではなく通常の削除を行う場合でも、テーブルのフル スキャンではすべてのデータ ブロックをふるいにかけ、データが含まれているかどうかを確認する必要があるためです。空のテーブルに対する DML は、以前にテーブルに大量のデータがあった場合、大量の I/O が発生する可能性があります。

私はまさにそれを行っているいくつかのコードを高速化しようとしています - それは永続的なテーブルに参加し、結果を呼び出し元に返すことができるように、一部のものをスクラッチパッドとして一時テーブルに押し込んでいます。一時テーブルはこのルーチンの利益のためだけにあるため、ルーチンの最後に削除しても安全ですが、親トランザクション内で何度も呼び出される可能性があるため、切り捨てることはできません (TRUNCATEは DDL であり、コミットしますまたは、同じトランザクション内の呼び出しが別の行を取得します。DELETE による消去は、特にテーブルにインデックスがなく、テーブルに対する選択が常にフル スキャンになるため、かなりのオーバーヘッドを引き起こします。

私が検討しているオプションはSAVEPOINT、ルーチンの開始時に を使用し、一時的な作業を行ってから、結果が返される直前にセーブポイントにロールバックすることです。別のオプションとして、ルーチンを自律型トランザクション内に配置することもできますが、それは C コードを PL/SQL ストアド プロシージャに移植することを意味し、呼び出し元によって挿入されたコミットされていないデータに一時テーブルを結合する必要がある場合は、とにかく機能しません。

私は12cで調査を行ったことに注意してください-このリリースでは一時テーブルにいくつかの改善がありました(https://oracle-base.com/articles/misc/temporary-tablesを参照)が、動作に影響はないと思いますwrt セーブポイント。

于 2016-03-31T16:09:56.030 に答える