トランザクションエントリに関する検証 その2

<トランザクションエントリに関する検証 その2>
ペンネーム しゅらん

今週も引き続きテーブルやインデックスを作成する際に設定するinitrans、
maxtransについて検証をしたいと思います。

(お断り)
今回は弊社マシンの不調により、前回使用した環境が使用できなくなってしま
ったため、急遽新しい環境を作成して検証を行いました。
よって、環境の違いにより若干の差異が生じる事があるかもしれませんが、
ご了承ください。

旧検証環境
OS:AIX5L
Oracle:8.1.7
DB_BLOCK_SIZE:8K

新検証環境
OS:Windows2000 Server
Oracle:8.1.7
DB_BLOCK_SIZE:8K

—maxtransに関する検証 ブロック格納率—

前回はmaxtransを255(実際には169)に設定して、200同時sessionと1同時ses
sionにてどのくらい格納効率の違いがあるかを検証しました。

—200 session—

TABLE_NAME                       NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
TBL_SHU1                           200000        850

850block→850*8K=約6.64MBを使用している。

—1 session—

TABLE_NAME                       NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
TBL_SHU1                           200000        665

665block→665*8K=約5.19MBを使用している。

上記のように、200同時sessionでinsertを行った場合の方が、格納効率が悪い
という結果が出ました。この違いはトランザクションレイヤーによるものなの
でしょうか。

詳細な検証の前に、今度はmaxtransを1にした場合、どういう結果になるのか、
1同時sessionとほぼ同様の結果が得られるのか、検証をしてみたいと思います。

—200 session、maxtrans 1—

CREATE TABLE TBL_SHU1 (ID   DATE DEFAULT SYSDATE,
                       TEXT CHAR(10))
                       INITRANS 1 MAXTRANS 1 PCTFREE 10
                       STORAGE ( INITIAL     20M
                                 NEXT        20M
                                 PCTINCREASE  0
                                 MAXEXTENTS  UNLIMITED);

上記のようにmaxtransを1にしてテーブルを作成後、前回と同じテストプログ
ラムを200session、1行insert&commitを1000回繰り返し(合計20万行挿入)に
て実行後analyzeを行い、結果を確認、するととんでもない結果が!

analyze table tbl_shu1 compute statistics;

select TABLE_NAME,NUM_ROWS,BLOCKS from dba_tables
where table_name='TBL_SHU1';

TABLE_NAME                       NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
TBL_SHU1                           200000     148989

148989ブロック!!!!! ということはブロックサイズが8Kなので、
なんと約1164MBも使用している。1ブロックに2レコードも格納されていない
ではないか。

これは一体何が起きているのだろうか??詳細に見てみよう。
再度同じようにmaxtransを1に設定して、テーブルを作成。

CREATE TABLE TBL_SHU2 (ID   DATE DEFAULT SYSDATE,
                       TEXT CHAR(10))
                       INITRANS 1 MAXTRANS 1 PCTFREE 10
                       STORAGE ( INITIAL     20M
                                 NEXT        20M
                                 PCTINCREASE  0
                                 MAXEXTENTS  UNLIMITED)
                       TABLESPACE TS_SHU2;

まず1sessionよりinsert文を実行、commitをきらない状態でSTOP。これで最初
のブロックのトランザクションエントリを使い切っている状態になる。

(実行)insert into tbl_shu2 (TEXT) values ('PPPPPPPPPP');

次に別のsessionより同様にinsert文を実行、ちなみにこのinsert文は待たさ
れることなく実行が出来た。
その後最初のsessionをcommit、次に2番目のsessionをcommitし、analyzeを実行
してみる。

analyze table tbl_shu2 compute statistics;

select TABLE_NAME,NUM_ROWS,BLOCKS from dba_tables
where table_name='TBL_SHU2';

TABLE_NAME                       NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
TBL_SHU2                                2          2

2ブロックになっている!しかし最初の1ブロックはセグメントヘッダーの可能
性もあるかも?truncateして、3つのsessionから上記と同様commitをきらない
ようにオペレーションを実行しanalyzeを実行後、dba_tablesを参照すると

SQL> select TABLE_NAME,NUM_ROWS,BLOCKS from dba_tables
  2  where table_name='TBL_SHU2';

TABLE_NAME                       NUM_ROWS     BLOCKS
------------------------------ ---------- ----------
TBL_SHU2                                3          3

やはり3ブロック使用している。

つまりブロック内のトランザクションエントリがmaxtransの値に達すると、
Oracleは次のトランザクションを待たせないために、ハイウォーターマークを
引き上げ、新しいブロックを割り当てていることが分かる。

それでは、ブロック内の残ったスペースは再利用されないのであろうか。
またフリーリスト(次のレコードの挿入先)はどのブロックを指しているのだ
ろうか、次回はその詳細を解明したいと思います。

以上、2児のパパになった茅ヶ崎にて