ログマイナーに関する検証 その4

< ログマイナに関する検証 その四 > ペンネーム チョビひげ

— ログ・マイナーで索引構成表を見よう —

前回はログ・マイナーで行連鎖を見た。
今回は索引構成表とクラスタを見てみたい。

索引構成表とは:
主キーを必ず指定しなければならず、B*ツリー索引におけるROW_IDの変わりに
非キー列(実際のデータ)がリーフエントリに格納される。つまり、ROW_IDを持
たない表である。

では、実際に以下の手順で索引構成表を作成し、データを挿入してみよう。

SQL> create table emp_ora (emp_no number, ename varchar2(40),
  2  constraint emp_pk primary key (emp_no))
  3  organization index
  4  tablespace users;

SQL> insert into emp_ora values(1,'chigasaki_meijin');

SQL> commit;

索引構成表へのデータのインサートがどのように表示されるか見てみよう。

SQL> select scn, data_obj#, row_id, operation, sql_redo, sql_undo
from v$logmnr_contents

SCN     DATA_OBJ#  ROW_ID              OPERATION  SQL_REDO                    SQL_UNDO
------- ---------- ------------------- ---------- --------------------------  ------
687683  0          AAAAAAAAAAAAAAAAAA  START      set transaction read write;        
687683  26055      AAAAAAAAAAAAAAAAAA  INTERNAL                
687684  0          AAAAAAAAAAAAAAAAAA  COMMIT     commit;        
***********************************************************

索引構成表自体がROW_IDを持たず、ROW_IDの変わりに直接データを格納してい
るため、当然のようにv$logmnr_contents表のROW_IDにも何も入ってないことが
分かる。また、SQL_REDO列も空白である。

では、v$logmnr_contents表からセグメントの情報も検索してみよう。

SQL> select scn, data_obj#, seg_name, seg_type_name, table_space from v$logmnr_contents;

SCN     DATA_OBJ#       SEG_NAME   SEG_TYPE_NAME   TABLE_SPACE
------- --------------- ---------- --------------- ------------
687683  0                        
687683  26055           EMP_PK     INDEX           SYSTEM
687684  0                        

上記のようにセグメント名がEMP_PKで、セグメントタイプもINDEXになってい
る。これは索引構成表の segment が index 構造で作成されているためである。

通常セグメントタイプがINDEXのものはログ・マイナーでは表示されないが、
索引構成表では表示されている。

それにしても、なぜTABLESPACEは表領域USRESに作成したにもかかわらず、
TABLE_SPACE列がSYSTEMになっているのであろうか。
では、TABLESPACEに関する情報をもう少し調べてみたい。

どの表領域を使用しているかUSER_INDEXES表から検索してみよう。

SQL> select table_name, index_name, tablespace_name
  2  from user_indexes where table_name = 'EMP_ORA';

TABLE_NAME      INDEX_NAME      TABLESPACE_NAME
--------------- --------------- ------------------------------
EMP_ORA         EMP_PK          USERS

テーブルを作成したときに指定した通りUSERSが検索される。
では、念のためUSER_TABLES表も検索してみよう。

SQL> select table_name, tablespace_name
  2  from user_tables where table_name = 'EMP_ORA';

TABLE_NAME      TABLESPACE_NAME
--------------- ------------------------------
EMP_ORA

TABLESPACE_NAMEが空白で検索されてしまう。
では、USER_EXTENTSを検索してみよう。

SQL> select tablespace_name, bytes
  2  from user_extents where segment_name='EMP_PK';

TABLESPACE_NAME      BYTES
--------------- ----------
USERS               131072

v$logmnr_contentsで表示されるTABLESPACEがなぜSYSTEMと表示されるかは不
明であるが、ログ・マイナー自体が索引構成表の操作をサポートしていないた
めなのかもしれない。

では、次にクラスタをログ・マイナーで見てみよう。
クラスタとは:
2つの表が1つの列(クラスタ・キー)を共有して結合し、同じデータブロックに
格納される。キーが共有されるため使用する記憶領域が少なくてすみ、クラス
タ化している表を結合する場合の処理時間も向上する。

では、クラスタを作成しデータを挿入後v$logmnr_contents表を見てみよう。

SQL> create cluster emp_cluster (deptno number)
  2  tablespace users;

SQL> create table emp_c (deptno number,
  2  emp_name varchar2(20))
  3  cluster    emp_cluster(deptno);

SQL> create table dept_c (deptno number,
  2  dept_name varchar2(20))
  3  cluster emp_cluster(deptno);

SQL> create index emp_cluster_idx on cluster emp_cluster;

SQL> insert into emp_c values(1,'ichiro');

SQL> insert into dept_c values(1,'sales');

SQL> insert into emp_c values(2,'niro');

SQL> insert into dept_c values(3,'operation');

SQL> commit;

SQL> select scn, row_id, sql_redo from v$logmnr_contents;
        
SCN     ROW_ID             SQL_REDO
------- ------------------ --------------------------------
687795  AAAAAAAAAAAAAAAAAA set transaction read write;
687795  AAAGXJAAFAAASBDAAB insert into "UNKNOWN"."Objn:26058"("Col[1]") 
                           values (HEXTORAW('69636869726f'));
687796  AAAGXJAAFAAASBDAAB insert into "UNKNOWN"."Objn:26059"("Col[1]") 
                           values (HEXTORAW('73616c6573'));
687797  AAAGXJAAFAAASBEAAB insert into "UNKNOWN"."Objn:26058"("Col[1]") 
                           values (HEXTORAW('6e69726f'));
687798  AAAGXJAAFAAASBFAAB insert into "UNKNOWN"."Objn:26059"("Col[1]") 
                           values (HEXTORAW('6f7065726174696f6e'));
687800  AAAAAAAAAAAAAAAAAA commit;

SQL_REDO列のオブジェクト名の変換がされてないのが分かる。
また、クラスタ索引が同じものでは同じデータ・ブロックに行が格納されるため、
ROW_IDが同じであることが分かる。

AAAGXJAAFAAASBDAAB ---- deptno=1
AAAGXJAAFAAASBDAAB ---- deptno=1

AAAGXJAAFAAASBEAAB ---- deptno=2

AAAGXJAAFAAASBFAAB ---- deptno=3
※deptnoはクラスタ索引

ROW_IDが同じであることによって、UNIQUEなクラスタ索引検索を行なった場合
に、ROWIDによるアクセスによって、同じブロックに格納されているクラスタ結
合された2つの表のデータにアクセスが可能であることが分かる。

v$logmnr_contens表とdba_objects表よりオブジェクト番号とオブジェクトが格
納されるセグメントの情報を検索してみよう。

SQL> select scn, data_obj#, data_objd#, operation from v$logmnr_contents;

SCN     DATA_OBJ#        DATA_OBJD#      OPERATION
------- ---------------- --------------- -----------
687795  0                0                START
687795  26058            26057            INSERT
687796  26059            26057            INSERT
687797  26058            26057            INSERT
687798  26059            26057            INSERT
687800  0                0                COMMIT

SQL> select owner, object_name, object_id, data_object_id, object_type
  2  from dba_objects
  3  where object_name in ('EMP_CLUSTER','EMP_C','DEPT_C');

OWNER      OBJECT_NAME      OBJECT_ID DATA_OBJECT_ID OBJECT_TYPE
---------- --------------- ---------- -------------- ------------------
SCOTT      DEPT_C               26059          26057 TABLE
SCOTT      EMP_C                26058          26057 TABLE
SCOTT      EMP_CLUSTER          26057          26057 CLUSTER

OBJECT_IDはオブジェクトのオブジェクト番号である。
また、DATA_OBJECT_IDはオブジェクトを含むセグメントのオブジェクト番号で
ある違うオブジェクトである2つの表EMP_CとDEPT_Cは領域的には同じセグメン
ト(オブジェクトEMP_CLUSTER)に格納されていることが確認できる。

今回は、索引構成表とクラスタをログ・マイナーで対応していないということ
で取り上げたが、ログ・マイナー以外にも対応していない機能があるので注意
されたい。

以上、秋の海も最高!の茅ヶ崎にて