マテビュー覚え書き

 次の現場でマテビューことマテリアライズド・ビューを使うことになりそうだったのでメモ代り。ちなみに就職して始めてはいった現場がOracle 8iだったため、いまでも惰性で待てマテリアライズド・ビューのことを「スナップショット」と呼んでしまう悲しい三十代が僕ですが何か?

 一噛みして気が済んだので、メモ
1.まずはマスター表(同期元)になる表を作成

SQL> create table mateview_master (
  2   col1 date,
  3   col2 number(8),
  4   col3 number(8),
  5   col4 char(9),
  6   col5 number(8)
  7  );

表が作成されました。

2.ついでなんでこの時点でマスター表にデータも突っ込んじゃう

SQL> begin
  2    for i in 1..10000 loop
  3      insert into mateview_master values (
  4        sysdate + i/3600,
  5        i,
  6        i * 2,
  7        to_char(sysdate + i/3600),
  8        i 
  9      ) ;
 10    end loop ;
 11    commit;
 12  end;
 13  /

PL/SQLプロシージャが正常に完了しました。

3.高速リフレッシュ(差分同期)させたいのでマテリアライズド・ビュー・ログを作成します

SQL> create materialized view log on mateview_master ;

マテリアライズド・ビュー・ログが作成されました。

4.お待ちかね。マテリアライズド・ビュー(同期先)を作成します

SQL> create materialized view mateview_replica
  2  as
  3  select col1, col3, col5 from mateview_master
  4  where  col5 < 100000
  5  ;

マテリアライズド・ビューが作成されました。

5.作成時点でのデータ件数を確認(マテビュー名の後ろに"BUILD DEFERRED"を指定していないので、データは入ってるはず)

SQL> select count(*) from mateview_replica ;

  COUNT(*)
----------
     10000

入ってますな。

6.マスター表に項目4のwhere句境界をまたがるデータを追加してみる。

SQL> begin
  2    for i in 95000..105000 loop
  3      insert into mateview_master values(
  4        sysdate + i/3600,
  5        i,
  6        i * 2,
  7        to_char(sysdate + i/3600),
  8        i
  9      );
 10    end loop ;
 11    commit ;
 12  end;
 13  /

PL/SQLプロシージャが正常に完了しました。

7.リフレッシュ(同期)してないのでまだ件数は変わらない

SQL> select count(*) from mateview_replica ;

  COUNT(*)
----------
     10000

8.リフレッシュしてみる。まずは完全リフレッシュ(完全同期)

SQL> exec dbms_mview.refresh('mateview_replica', 'c') ;

PL/SQLプロシージャが正常に完了しました。

SQL> select count(*) from mateview_replica ;

  COUNT(*)
----------
     15000

反映(実際にはマテビューデータを全消去してからマスター表のデータを入れている)されてる

9.続いて高速リフレッシュ(差分同期)

SQL> exec dbms_mview.refresh('mateview_replica', 'f') ;

PL/SQLプロシージャが正常に完了しました。

SQL> select count(*) from mateview_replica ;


  COUNT(*)
----------
     15000

まぁ、差分無いからねぇ……。

10.今回作成したのは「読み取り専用マテリアライズド・ビュー」なのでDML操作は無効になる

SQL> insert into mateview_replica values (
  2    sysdate, 2, 0 
  3  ) ;
insert into mateview_replica values (
            *
行1でエラーが発生しました。:
ORA-01732: このビューではデータ操作が無効です

SQL> delete from mateview_replica ;
delete from mateview_replica
            *
行1でエラーが発生しました。:
ORA-01732: このビューではデータ操作が無効です

SQL> update mateview_replica set col1=sysdate ;
update mateview_replica set col1=sysdate
       *
行1でエラーが発生しました。:
ORA-01732: このビューではデータ操作が無効です

11.でもtruncateは通っちゃう

SQL> truncate table mateview_replica ;

表が切り捨てられました。

SQL> select count(*) from mateview_replica ;

  COUNT(*)
----------
         0

12.この状態で高速リフレッシュをやると、怒られる

SQL> exec dbms_mview.refresh('mateview_replica', 'f') ;
BEGIN dbms_mview.refresh('mateview_replica', 'f') ; END;

*
行1でエラーが発生しました。:
ORA-32320: "KWY"."MATEVIEW_REPLICA"のREFRESH FASTはコンテナ表PMOPの後ではサポートされていません 
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2537
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2743
ORA-06512: "SYS.DBMS_SNAPSHOT", 行2712
ORA-06512: 行1

エラーメッセージとしてはORA-32321が出るのが正しいような気もするんだけど、まぁORA-32320が出る。対処方の完全リフレッシュ実施は、まぁ、その通りなんだけど。

$ oerr ora 32320
32320, 00000, "REFRESH FAST of \"%s\".\"%s\" unsupported after container table PMOPs"
// *Cause:  A Partition Maintenance Operation (PMOP) has been performed on the 
//          materialized view, and no materialized view supports
//          fast refersh after container table PMOPs.
// *Action: Use REFRESH COMPLETE.  Note: you can determine why your 
//          materialized view does not support fast refresh after PMOPs using
//          the DBMS_MVIEW.EXPLAIN_MVIEW() API.
$ 
$ 
$ 
oerr ora 32321
32321, 00000, "REFRESH FAST of \"%s\".\"%s\" unsupported after detail table TRUNCATE"
// *Cause:  A detail table has been truncated and no materialized view
//          supports fast refersh after a detail table has been truncated 
// *Action: Use REFRESH COMPLETE.  Note: you can determine why your 
//          materialized view does not support fast refresh after TRUNCATE using
//          the DBMS_MVIEW.EXPLAIN_MVIEW() API.

こんな感じ。