SQL*Loader で TRUNCATE とすると、ロードする前に TRUNCATE してくれるが、セグメント解放してくれなかったので調べた。
SELECT *FROM DBA_SEGMENTS WHERE OWNER = 'XXX' AND SEGMENT_NAME='テーブル名' AND SEGMENT_TYPE='TABLE';
とするとセグメントの情報を取得できる。BYTES や BLOCKS を見れば良い。詳細は
マニュアル参照。
TRUNCATE すると、BLOCKS が 1 になるはずだが、そうなっていなかった。
※CREATE TABLE で
SEGMENT CREATION DEFERRED を指定していると 0 になると思われる。
SQL*Loader のマニュアルを見ると次のように書いてあった。
TRUNCATEオプションを使用すると、SQLのTRUNCATE TABLE table_name REUSE STORAGE文が実行され、表のエクステントが再利用されます。
TRUNCATEオプションにより、表またはクラスタからすべての行が短時間で効率的に削除されるため、最大限の処理パフォーマンスを実現できます。
TRUNCATE TABLE のデフォルトは DROP STORAGE で、セグメントが解放されるが、REUSE STORAGE だと解放されない。デカイテーブルで DROP STORAGE すると時間がかかる時がある。
それが嫌だから、Loader の TRUNCATE は REUSE STORAGE なのだろうが、オプションで変更できない。
SQL*Loader でセグメント解放したい場合は、事前に TRUNCATE TABLE すべし、ということね。
VirtualBox に CentOS/Redhat Enterprise Linux/Oracle Enterprise Linux の 32bit/64bit をいろいろな設定でインストールしようとしても全部出来なかった。
インストールして最初のリブート時にエラーで落ちるし、再起動後の初期設定でも kdump の設定の後同じように落ちてつかえない。
使っているマシンが DELL の INSPIRON 15 M5030 というやつで、ホストOSが Windows7 64bit、CPU が Athlon Ⅱ P320 という代物。
AMD Virtualization(AMD-V)をBIOSで有効・無効にしてみたがだめ。
VirtualBox + AMDの相性がわるいもよう。
最近、VMwareを使っていなかったのでしらなかったが、VMware Serverはもうサポートされず、個人Useでは、VMware Player でVMイメージを作れるようになっていたので、そっちでやってみたらあっさり32bit/64bitともにインストールできた。
ユーザ数の違いが品質の違いにあらわれているのかも。
ちなみ、microsoft の Windows7 HomePremium でも動く仮想化ソフト(名前は忘れた)も入れてみたが、VirtualBoxよりもダメだった。
マテビューの元表に対してのTRUNCATE
の検証をしているときに、ORA-12034 が発生した。
良くわからないのが、起きたのが1回だけで何回同じことをやっても発生しない。
マテビューの件数が減っていることから、リフレッシュ自体は完了しているが、その後でこけているっぽい。
超微妙なタイミングで発生するOracleのバグ?
マニュアルで関係しそうなものを見てみた。
まず疑ったのは、
マテビューログのパージ。
CREATE MATERIALIZED VIEW LOG でログのパージタイミングを指定できる。
mv_log_purge_clauseIMMEDIATE
SYNCHRONOUS
: マテリアライズド・ビュー・ログは、リフレッシュの直後に消去されます。これはデフォルトです。
IMMEDIATE
ASYNCHRONOUS
: マテリアライズド・ビュー・ログは、リフレッシュ操作後に、別のOracleスケジューラ・ジョブで消去されます。
START
WITH
、NEXT
およびREPEAT
INTERVAL
は、CREATE
またはALTER
MATERIALIZED
VIEW
LOG
文で開始される、マテリアライズド・ビューのリフレッシュに依存しないスケジュール実行のパージを設定します。これは、CREATE
またはALTER
MATERIALIZED
VIEW
文の、スケジュール実行のリフレッシュ構文と似ています
とあり、今回はオプションを何も指定していないので同期で削除されるから問題なさそう。
次に疑ったのは、
COMMIT SCNWITH ROWID, PRIMARY KEY で
マテビューを作っている。デフォルトでは「COMMIT SCN句を使用しない場合、マテリアライズド・ビュー・ログはタイムスタンプ・ベースになり」と言っているので、これに起因する問題か?
と思ったが、「COMMIT SCN」はローカル
マテビューでしか使用できないので、これで回避することは出来ない。
結局理由わからずで、起きないことを祈るのみ。
運用では、TRUNCATEは基本無く、更新しているタイミングでリフレッシュはしないのでまず起きないと期待したい。
SQL> truncate table tbl03;
表が切り捨てられました。
SQL>
SQL> select UNUSABLE, KNOWN_STALE, INVALID from USER_MVIEW_ANALYSIS WHERE MVIEW_NAME='MV01';
UN KN IN
-- -- --
N N Y
SQL> select count(*) from mv01;
COUNT(*)
----------
2
SQL> exec DBMS_MVIEW.REFRESH( 'MV01', '?');
BEGIN DBMS_MVIEW.REFRESH( 'MV01', '?'); END;
*
行1でエラーが発生しました。:
ORA-12034: "TEST"."TBL03"のマテリアライズド・ビュー・ログは最終リフレッシュよりも新しいものです。
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2563
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2776
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2745
ORA-06512: 行1
SQL> select UNUSABLE, KNOWN_STALE, INVALID from USER_MVIEW_ANALYSIS WHERE MVIEW_NAME='MV01';
UN KN IN
-- -- --
N Y N
SQL> select count(*) from mv01;
COUNT(*)
----------
1