ロックに関する検証 その7

~ロックに関する検証 その7~
ペンネーム ちゃむ

前回は、ビットマップ・インデックスの構造の詳細に迫ってみた。
今回は、BLOCK DUMPによりビットマップ・インデックスの構造をさらに詳細に
見ていこう。この構造が分からないと、ビットマップ・インデックスのロック
の問題を理解することはできない。

では、BLOCK DUMPを見てみよう。

BITMAP_4のBLOCK DUMPをすべて取得するためには、以下のSQLでBLOCK_ID等を取
得(結果をファイルに出力)した後、そのスクリプト(ファイル)を実行するこ
とにする。

SQL> SET FEEDBACK OFF
SQL> SET PAGES 0
SQL> SET HEAD OFF
SQL> SET TERMOUT OFF

SQL> SPOOL C:B_DUMP.SQL
SQL> SELECT 'ALTER SYSTEM DUMP DATAFILE ' || FILE_ID ||  ' BLOCK '  || BLOCK_ID || ';'
     FROM DBA_EXTENTS WHERE SEGMENT_NAME = 'BITMAP_4'
     ORDER BY BLOCK_ID;

上記のSQLによって出力されたファイルを実行する。

SQL> @C:B_DUMP.SQL

以下 C:B_DUMP.SQLの中身を抜粋

ALTER SYSTEM DUMP DATAFILE 4 BLOCK 18333;
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 22960;
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 23025;
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 23043;
          :         :          :
          :         :          :
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 83055;
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 83070;
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 83132;
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 83164;

それでは、ビットマップ・インデックスのBLOCK DUMPの中身を覗いてみよう。
まず始めに、ブランチ・ブロックから見ていくことにしよう。
セグメント・ヘッダーとBranchブロックが同じエクステントに1ブロックずつ格
納されたという話をしたが(前回)、その都合上、上記のスクリプトには、branch
ブロックのBLOCK DUMPを取得するためのスクリプトは含まれていない。前回の
TREE DUMPから、BLOCK DUMPの取得に必要なブランチ・ブロックのBLOCK_ID、
FILE_IDを知ることができる。

******************* 前回のTREE DUMPのブランチ部分 ********************
branch: 0x1005e02 16801282 (0: nrow: 88, level: 1)  ← branch block
**********************************************************************
SQL> SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16801282) FILE_ID,
            DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16801282) BLOCK_ID
     from dual;

  FILE_ID  BLOCK_ID
--------- ---------
        4     24066

SQL> ALTER SYSTEM DUMP DATAFILE 4 BLOCK 24066 ;

上記の結果(ダンプ)は、以下のURLに示す。nrow: 88の個数の部分も確認して
頂きたい。

このインデックスは、以下のようにカーディナリティが 4 のカラムに対して作
成したビットマップ・インデックスである。

SQL> select distinct mgr from t10man_copy_4 ;

MGR
--------
 0000000
 0000001
 0000002
 0000003

細かい話であるが、実は、MGR列の一番左側に空白が1つ存在している。これは、
前々回に以下のようなSQL文を用いてテーブルを作成した際、TO_CHAR関数のと
ころで、「FM」をつけて空白を取り除かなかったからである。
to_char(mod(EMPNO,4),’FM0000000′)とすれば空白は取り除かれるが、検証に当
たっては特に支障がないので、このままのデータで行なう。

SQL> CREATE TABLE T10MAN_COPY_4 AS
     SELECT EMPNO,ENAME,JOB,to_char(mod(EMPNO,4),'0000000') MGR,
            HIREDATE,SAL,COMM,DEPTNO
     FROM T10MAN_ORG ;

ダンプ中の「col 0」はカラム値を表している。これらは、以下の様な値を示し
ている。

20 → 空白
30 → 0
31 → 1
32 → 2
33 → 3

col 0; len 8; (8):  20 30 30 30 30 30 30 30 ←  0000000
col 0; len 8; (8):  20 30 30 30 30 30 30 31 ←  0000001
col 0; len 8; (8):  20 30 30 30 30 30 30 32 ←  0000002
col 0; len 8; (8):  20 30 30 30 30 30 30 33 ←  0000003

前回、B-Treeインデックスとビットマップ・インデックスのブランチ・ブロッ
クは若干構造が異なるという話をしたが、その違いが「col 1」である。この値
は、B-Treeインデックスには存在しない。この値は、カラム値が変わる毎に、決
まった値が現れる。

col 1; len 3; (3): 01 01 09

以下のURL(以前説明したビットマップ・インデックスのイメージ図)に示すよ
うに、カラム値毎にstart rowid、end rowid、ビットマップセグメントをそれぞ
れ持っているが、カーディナリティが 4 であれば、このようなデータが4つ存在する。

この「01 01 09」がおそらく、start rowidとend rowidの個数や範囲を表わす

ために使用されているようだが、これはあくまでも推測であって、定かなもの
ではない。

また、ブランチ・ブロックの先頭行だけカラム値が存在していない構造となっ
ている。以下のURLで、ブランチ・ブロックのイメージを確認してほしい。

これは、BLOCK DUMPから見ると以下の部分に当たる。

kdxbrlmc 16801190=0x1005da6

最後に、ビットマップ・インデックスの核心部分である、リーフ・ブロックの
ダンプを示す。この構造を見ただけで、ロックの問題に気付いた読者もいるで
あろう。

ダンプ中のビットマップ・セグメントの殆どが、「11」「22」「44」「88」と

いった数字であるが、これらは16進数なので本来は、「00010001」「00100010」
「01000100」「10001000」などといった値(ビット)を表しているのである。
これらはすべて、4ビット毎に「1」が現れているが、この理由は、ビットマップ・
インデックスが作成してあるMGR列のカーディナリティが 4 で、
to_char(mod(EMPNO,4),’0000000′)のようにmod関数を用いて作成したため、ROWID
が4つ進む毎に、同じ値が現れるといった構造になっているからである。

以上 茅ヶ崎にて