ローカルエクステントマネージメントに関する検証 その3

<ローカルエクステントマネージメントに関する検証 その3>
ペンネーム ちゃむ

————————————————————————–
8iからの新機能ローカルエクステントマネージメントを以下「LOCAL」と呼ぶ。
従来のデータディクショナリーでエクステントを管理する方法を以下「DICTIONARY」
と呼ぶ。
————————————————————————–

前回は、実際に「LOCAL」がビットマップ管理している様子を見てきた。
今回は、「LOCAL」で管理されている領域に対して、実際にオブジェクトを作成
した時の、ビットマップ情報の変化について見てみよう。
以下に紹介するすべての検証結果は、DB_BLOCK_SIZE = 2Kで行ったものである。

「LOCAL」を作成する

CREATE TABLESPACE tbs_u_1 DATAFILE 'c:tbs_u_1.ora' SIZE 1024k
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 8K;

作成直後のDBA_FREE_SPACEの様子

TABLESPACE_NAME  FILE_ID  BLOCK_ID  BYTES   BLOCKS
--------------------------------------------------
TBS_U_1          25       33        983040  480

この状態で、以下のようなテーブルを作成してみよう。
このテーブルは、空領域のすべて(960K(983040))を使い切らせるためのも
のである。

CREATE TABLE tbs_u_1_tbl (col number)
storage (initial 960k next 2k minextents 1 pctincrease 0)
tablespace tbs_u_1;

このときのブロックダンプは?

ALTER SYSTEM DUMP DATAFILE 25 BLOCK 3;
File Space Bitmap Block: 
BitMap Control: 
RelFno: 25, BeginBlock: 33, Flag: 0, First: 120, Free: 14216 
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFF00 0000000000000000 0000000000000000 1行目
0000000000000000 0000000000000000 0000000000000000 0000000000000000 2行目
0000000000000000 0000000000000000 0000000000000000 0000000000000000 3行目
       :                        :                       :
       :                        :                       :
                            (途中省略)
       :                        :                       :
       :                        :                       :
0000000000000000 0000000000000000 0000000000000000 0000000000000000 54行目
0000000000000000 0000000000000000 0000000000000000 0000000000000000 55行目
0000000000000000 0000000000000000 0000000000000000 0000000000000000 56行目
End dump data blocks tsn: 36 file#: 25 minblk 3 maxblk 3

予想どおり、16進数で表わされているビットマップ情報に変化が生じた。
(テーブルを作成する前は、すべて 0 であった)

そもそも、このビットマップ情報は、テーブルスペースtbs_u_1の場合、480ブ
ロック分(983040 / 2048)の「使用」および「未使用」の状態を表わせなけれ
ばならない。
上記のダンプの状態を考察してみよう。

1.16進数一桁で表現できる状態の数は4ビットなので「4」通り
(1つのビットで「使用」「未使用」を表している)
2.領域を確保していく単位は、UNIFORM SIZE 8K(4ブロック)
この場合、「4」ブロックを1つの塊(単位)として、1ビットで「使用」
「未使用」を表すことになる
3.上記ダンプ中の F の数 → 「30」個

上記の1、2,3の「」で括られた数字を掛け合わせると、4×4×30=480になる。
これは、始めにテーブルスペースを作成した直後の未使用ブロック数、つまりtbs
_u_1_tblの総使用可能領域と一致する。

ダンプ中の16進数一桁で、4つの状態×4ブロック単位=16ブロック分のステータス
(使用/未使用)を表現することができる。
その16進数が30個あるので、16ブロック分×30個=480ブロック分という訳である。
したがって、このテーブルスペースtbs_u_1は、480ブロック分の「使用領域」また
は「未使用領域」であるという判断を、30桁分の16進数を用いて管理しているとい
うことだ。

ビットマップ管理されている領域の「0000000000000000」の16進数の列は、
16ブロック(16進数一桁で表現できる状態のブロック数)×16( 0 の数)= 256通り
の状態を表現できる。この「0000000000000000」が、1ブロック中に
4(列の数)× 56(行の数)=224 セット存在している。つまり、1ブロックで
224×256=57344ブロック分の「使用」および「未使用」の状態を表現できる計算
になる。さらに、このビットマップ管理している情報は、前回の結果から
block_id=3からblock_id=32の30ブロック存在していた。

つまり、理論上、全部で、57344*30=1720320ブロック(3440640k)の「使用」お
よび「未使用」領域の状態を管理できることになる。

では、SIZEが少し大き目の「LOCAL」を作成してみよう。
以下のテーブルスペース中、32ブロック分はビットマップ管理などに使用され
ることから、実質105600ブロックが未使用領域として確保されるはずである。
211264K / 2K(ブロック・サイズ) – 32(管理領域) = 105600

CREATE TABLESPACE tbs_u_1_b1 DATAFILE 'd:tbs_u_1.ora' SIZE 211264k
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 8K;

作成直後のDBA_FREE_SPACEの様子

TABLESPACE_NAME  FILE_ID  BLOCK_ID  BYTES      BLOCKS
-----------------------------------------------------
TBS_U_1_B1       28       33        117440512  57344
TBS_U_1_B1       28       57377     98828288   48256

おや!オヤ!OYA!、なんで2行出力されているんだ。
57344+48256=105600ブロックだから使用できる空領域は予定どおりだけど・・・
あれ!アレ!ARE!、しかも、1行目のBLOCKS=57344・・・なんか見たことがある
数値だぞ!!

これは、さっき計算したビットマップ情報の入っている1ブロックで表わせる
「使用」および「未使用領域」の数だ。

まさか、この表示のされ方。57344ブロックまでのエクステントしか確保できな
いのであろうか?
念のため、60000ブロックを使用するテーブルを作成できるか試してみよう。

CREATE TABLE tbs_u_1_b1_tbl (col number)
storage (initial 120000k next 2k minextents 1 pctincrease 0)
tablespace tbs_u_1_b1;

よかった、正常に作られた。
テーブル作成直後のDBA_FREE_SPACEの様子は?

TABLESPACE_NAME  FILE_ID  BLOCK_ID  BYTES      BLOCKS
-----------------------------------------------------
TBS_U_1_B1       28       60093     93265920   45540


   テーブルで使用したエクステント (60000ブロック)
+ 上記の未使用ブロック            (45540ブロック)
---------------------------------------------------
   始めの未使用ブロック           (105600ブロック)

ぜんぜん問題ないようだ。

では、なぜ、空ブロックが2行表示されてしまうのだろうか?
これは、DBA_FREE_SPACEビュー自体の問題であろう。
以下にDBA_FREE_SPACEビューの定義を示す。
union all 以下のselect 文が「LOCAL」の未使用領域を示すための文である。
(ts.bitmapped 0のところから判断できる。)
ちなみに、union allより上の部分は?DICTIONARY」の未使用領域を示すため
の文である。
(ts.bitmapped = 0のところから判断できる)

create or replace view DBA_FREE_SPACE
    (TABLESPACE_NAME, FILE_ID, BLOCK_ID,
     BYTES, BLOCKS, RELATIVE_FNO)
as
select ts.name, fi.file#, f.block#,
       f.length * ts.blocksize, f.length, f.file#
>from sys.ts$ ts, sys.fet$ f, sys.file$ fi
where ts.ts# = f.ts#
  and f.ts# = fi.ts#
  and f.file# = fi.relfile#
  and ts.bitmapped = 0
union all
select /*+ ordered use_nl(f) use_nl(fi) */
       ts.name, fi.file#, f.ktfbfebno,
       f.ktfbfeblks * ts.blocksize, f.ktfbfeblks, f.ktfbfefno
>from sys.ts$ ts, sys.x$ktfbfe f, sys.file$ fi
where ts.ts# = f.ktfbfetsn
  and f.ktfbfetsn = fi.ts#
  and f.ktfbfefno = fi.relfile#
  and ts.bitmapped  0 and ts.online$ in (1,4) and ts.contents$ = 0

ここで、from句の元データの違いに注目しよう。
「LOCAL」はx$ktfbfeを元データとしている。
x$ktfbfeを直接見ると、以下のようになる。
DBA_FREE_SPACEは、以下の内容をそのまま出力しているからであろう。

INDX  INST_ID  KTFBFETSN  KTFBFEFNO  KTFBFEBNO  KTFBFEBLKS
----------------------------------------------------------
1     1        56         28         33         57344
2     1        56         28         57377      48256

じゃあなんで、x$ktfbfeはこんなデータの入り方をしているのかって言われたら
困ってしまうが、あえて言うならば、「これが仕様です!!」ってなってしまう。

以上 烏帽子岩が遠くに見える 茅ヶ崎にて