マテリアライズド・ビュー・ログを検証する（１）


# マテリアライズド・ビュー・ログとは
マテリアライズド・ビュー・ログは、マテリアライズド・ビューの元となるテーブルに対して作成するオブジェクトで、CREATE MATERIALIZED VIEW LOG文で作成します。マテリアライズド・ビュー・ログにはテーブルに対する更新レコード情報が書き込まれます。マテリアライズド・ビュー・ログが存在することで、マテリアライズド・ビューの前回リフレッシュからのレコード差分を特定することができます。この機能によりマテリアライズド・ビューの高速リフレッシュを実現しています。
  CREATE MATERIALIZED VIEW LOG文のマニュアルはわかりにくく、これまで詳しく検証したことが無いため、いくつか例を実行しながら内部を探ります。
　下記の例では主キーを持つテーブルを作成し、テーブルに対してマテリアライズド・ビュー・ログも作成しています。

```
SQL> CREATE TABLE mtest1(c1 NUMBER PRIMARY KEY, c2 VARCHAR2(10));

表が作成されました。

SQL> CREATE MATERIALIZED VIEW LOG ON mtest1;

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

# マテリアライズド・ビュー・ログの構成
マテリアライズド・ビュー・ログを作成すると、以下のオブジェクトが作成されます。マテリアライズド・ビュー・ログ実体は差分情報を構成するテーブルとインデックスです。

|オブジェクト名|オブジェクト種別|用途|
|:---|:---|:---|
|MLOG$_{テーブル名}|TABLE|差分格納テーブル|
|I_MLOG$_{テーブル名}|INDEX|MLOG$_{テーブル名}テーブルに対するインデックス|
|RUPD$_{テーブル名}|GLOBAL TEMPORARY TABLE|差分格納一時テーブル|

RUPD\$で始まるテーブルはグローバル一時テーブルです。常に作成されるわけではなく、CREATE MATERIALIZED VIEW LOG文のオプションによっては作成されません。

```
SQL> SELECT table_name, temporary, duration FROM user_tables;

TABLE_NAME                     T DURATION
------------------------------ - ---------------
MLOG$_MTEST1                   N null
MTEST1                         N null
RUPD$_MTEST1                   Y SYS$SESSION
```

マテリアライズド・ビュー・ログの確認には{DBA|ALL|USER}\_MVIEW\_LOGSビューを確認します。
RUPD\$ではじまるテーブル名はSYS.MLOG\$テーブルのTEMP\_LOG列から確認できます。

```
SQL> SELECT master, log_table FROM user_mview_logs;

MASTER                         LOG_TABLE
------------------------------ ------------------------------
MTEST1                         MLOG$_MTEST1

SQL(SYS)> SELECT master, log, temp_log FROM sys.mlog$;

MASTER                         LOG                            TEMP_LOG
------------------------------ ------------------------------ ------------------------------
MTEST1                         MLOG$_MTEST1                   RUPD$_MTEST1
```

マテリアライズド・ビュー・ログの削除はDROP MATERIALIZED VIEW LOG文を実行します。MLOG\$テーブルはDROP TABLE文による削除はできませんが、通常のテーブルであるためINSERT / UPDATE / DELETE 文は受け付けます。RUPD\$テーブルはDROP TABLE文で削除することもできます。

```
SQL> DROP TABLE MLOG$_mtest1;
DROP TABLE MLOG$_mtest1
           *
行1でエラーが発生しました。:
ORA-32417: "SCOTT"."MLOG$_MTEST1"の削除には、DROP MATERIALIZED VIEW
LOGを使用する必要があります


SQL> DROP TABLE RUPD$_mtest1;

表が削除されました。
```

# CREATE MATERIALIZED VIEW LOG文の実行

## WITH句に指定する値
  マテリアライズド・ビュー・ログには元のテーブルに対する更新情報が格納されますが、どのような情報を格納するかをCREATE MATERIALIZED VIEW 文の WITH 句で指定します。これらの値は複数指定することができます。

### PRIMARY KEY
　主キーの値をそのまま格納します。主キーが存在する場合のデフォルト値です。主キー以外の列を追加することもできます。

### SEQUENCE
　マニュアルには「追加の順序情報を提供する順序値をマテリアライズド・ビュー・ログに記録できます。」と書かれていますが、これでは何のことかわかりません。実態はレコードの格納順序を記録します。ダイレクト・ロードを使用する場合に必要です。更新される列を追加できます。

SEQUENCEの指定が必要な条件は[マニュアル「データ・ウェアハウス・ガイド」](https://docs.oracle.com/cd/F19136_01/dwhsg/basic-materialized-views.html#GUID-932B8CD4-BF60-419A-9202-8A9FD5D24024) に記載があります。

```
SQL> INSERT INTO mtest1 SELECT LEVEL c1, 'data1' c2 FROM DUAL CONNECT BY LEVEL <= 10000;

10000行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL> SELECT COUNT(*) FROM MLOG$_mtest1;

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

SQL> SELECT C1, SEQUENCE$$ FROM MLOG$_mtest1 WHERE C1 < 10;

        C1 SEQUENCE$$
---------- ----------
         1      10001
         2      10002
         3      10003
         4      10004
         5      10005
         6      10006
         7      10007
         8      10008
         9      10009
```

### ROWID
　更新されたレコードのROWIDを記録します。更新される列を追加できます。

### COMMIT SCN
　差分を把握する場合にCOMMIT SCNを使います。マテリアライズド・ビューをリフレッシュするタイミングをタイムスタンプではなく、SCNを使って特定するようになります。更新される列を追加できます。

### OBJECT ID
　オブジェクト・テーブルの場合に必要になります。ヒープ・テーブルでは指定できません。

## WITH句によるテーブルの差異
  WITH句に指定する値によって自動生成されるテーブルがどのように変化するかを確認しました。ROWIDを指定した場合、RUPD\$テーブルは作成されないことがわかりました。

MLOG\$\_{TABLE}テーブルの変化
	
|列名		|データ型|指定無	|PRIMARY KEY|SEQUENCE|ROWID|COMMIT SCN	|全部|
|:---		|:---	|:---	|:---	|:---	|:---	|:---	|:---|
|主キー列	|-	|〇	|〇	|〇	|×	|〇	|〇|
|追加列	　　　　|-	|-	|×	|〇	|〇	|〇	|〇|
|M_ROW$$	|VARCHAR2(255)	|×	|×	|×	|〇	|×	|〇|
|SEQUENCE$$ |NUMBER	|×	|×	|〇	|×	|×	|〇|
|SNAPTIME$$	|DATE	|〇	|〇	|〇	|〇	|×	|×|
|DMLTYPE$$	|VARCHAR2(1)	|〇	|〇	|〇	|〇	|〇	|〇|
|OLD_NEW$$	|VARCHAR2(1)	|〇	|〇	|〇	|〇	|〇	|〇|
|CHANGE_VECTOR$$|RAW(255)	|〇	|〇	|〇	|〇	|〇	|〇|
|XID$$		|NUMBER		|〇	|〇	|〇	|〇	|〇	|〇|
							
RUPD\$\_{TABLE}テーブルの変化

|列名|データ型|指定無|PRIMARY KEY|SEQUENCE|ROWID|COMMIT SCN|全部|
|:---|:---|:---	|:---|:---|:---|:---|:---|
|主キー列	|- |〇	|〇 |〇	|no table|〇|〇|
|DMLTYPE$$	|VARCHAR2(1)	|〇|〇|〇|no table|〇|〇|
|SNAPID		|NUMBER(38)	|〇|〇|〇|no table|〇|〇|
|CHANGE_VECTOR$$ |RAW(255)	|〇|〇|〇|no table|〇|〇|

## 主キーが存在しないテーブルに対する作成

主キーが存在しないテーブルに対してはROWID以外の指定はエラーになります。

```
SQL> CREATE TABLE mtest2(c1 NUMBER, c2 VARCHAR2(10));

表が作成されました。

SQL> CREATE MATERIALIZED VIEW LOG ON mtest2;
CREATE MATERIALIZED VIEW LOG ON mtest2
*
行1でエラーが発生しました。:
ORA-12014: 表'MTEST2'に主キー制約がありません

SQL> CREATE MATERIALIZED VIEW LOG ON mtest2 WITH ROWID;

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

SQL> DROP MATERIALIZED VIEW LOG ON mtest2;

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

SQL> CREATE MATERIALIZED VIEW LOG ON mtest2 WITH SEQUENCE;
CREATE MATERIALIZED VIEW LOG ON mtest2 WITH SEQUENCE
*
行1でエラーが発生しました。:
ORA-12014: 表'MTEST2'に主キー制約がありません

SQL> CREATE MATERIALIZED VIEW LOG ON mtest2 WITH COMMIT SCN;
CREATE MATERIALIZED VIEW LOG ON mtest2 WITH COMMIT SCN
*
行1でエラーが発生しました。:
ORA-12014: 表'MTEST2'に主キー制約がありません
```

まずはマテリアライズド・ビュー・ログの作成について検証しました。次にマテリアライズド・ビューのリフレッシュとの関係を検証したいと思います。