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

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

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

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

先週、先々週は読者からの質問に関する検証を行いました。

ちょっと戻りますが、第1回~第3回は同時複数sessionからテーブルへのインサ
ートを行ったり、maxtransを1にしてどうなるかの検証を行いました。

そして、トランザクションエントリを使い切ってしまうと、ブロックにいくら
空き領域が残っていても、トランザクションを待たせないために、新たなブロ
ックを確保してしまい、インサートが出来なかったブロックをフリーリストか
ら外してしまった。そのため場合によっては非常に格納効率が悪くなってしま
った事があった。

今週はインデックスについて同様の検証を行いたいと思います。
インデックスも同じような動きをするのか?それとも・・・・?

第1回で使用したテーブルtbl_shu1を使用して検証を行います。

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

このテーブルのIDカラムにINDEXを作成してみます。

CREATE INDEX IDX_TBL_SHU1 ON TBL_SHU1(ID)
             INITRANS 2 MAXTRANS 255 PCTFREE 10
             STORAGE ( INITIAL     20M
                       NEXT        20M
                       PCTINCREASE  0
                       MAXEXTENTS  UNLIMITED);

これで準備完了

このテーブルに1sessionから20万件のインサートを行った場合、
また200sessionからそれぞれ1000件、合計20万件のインサートを行った場合、
INDEXの領域の使用方法にどういう違いが出るのかを検証します。

—1sessionから20万件のインサート—

まずは1sessionからインサートを行い、基礎情報を取得します。
テストプログラムは、おなじみの弊社開発言語POPSQLで作成しています。

LOOP(i=0; i>200000; i++)
	SQL insert into tbl_shu1 (TEXT) values ('PPPPPPPPPP');
	COMMIT
ENDLOOP
ANALYZE INDEX IDX_TBL_SHU1 COMPUTE STATISTICS;

SELECT INDEX_NAME,TABLE_NAME,NUM_ROWS,LEAF_BLOCKS FROM DBA_INDEXES 
WHERE INDEX_NAME='IDX_TBL_SHU';

INDEX_NAME    TABLE_NAME    NUM_ROWS LEAF_BLOCKS
------------  ----------- ---------- -----------
IDX_TBL_SHU1  TBL_SHU1        200000         476

リーフブロックとして、476ブロック(約3.71MB)使用している。

—200同時sessionからそれぞれ1000件のインサート—

次にTBL_SHU1をトランケート後、
200sessionからそれぞれ1000件、合計20万件のインサートを行う。

ANALYZE INDEX IDX_TBL_SHU1 COMPUTE STATISTICS;

SELECT INDEX_NAME,TABLE_NAME,NUM_ROWS,LEAF_BLOCKS FROM DBA_INDEXES 
WHERE INDEX_NAME='IDX_TBL_SHU';

INDEX_NAME    TABLE_NAME    NUM_ROWS LEAF_BLOCKS
------------  ----------- ---------- -----------
IDX_TBL_SHU1  TBL_SHU1        200000        1345

1345ブロック(約10.51MB)、つまり約2.8倍の領域が使用されている。
これはやはりトランザクションエントリによるものであろうか?

20万件で 476ブロック → 1ブロック平均420行
20万件で1345ブロック → 1ブロック平均149行

—ダンプの確認—

ではダンプを取って確かめてみよう。ダンプの取り方については
<トランザクションエントリに関する検証 その3>を参照。

1ブロック目はセグメントヘッダー、2ブロック目はブランチなので
3ブロック目から見てみよう。

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   xid:  0x0010.046.00000098    uba: 0x00801e23.0008.01  CBU-    0  scn 0x0000.000e86cf
0x02   xid:  0x0000.000.00000000    uba: 0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x03   xid:  0x000d.021.00000098    uba: 0x008019b7.0006.06  C-U-    0  scn 0x0000.000e8651
0x04   xid:  0x0000.000.00000000    uba: 0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x05   xid:  0x0000.000.00000000    uba: 0x00000000.0000.00  ----    0  fsc 0x0000.00000000
 
Leaf block dump
===============
header address 114984100=0x6da84a4
kdxcolev 0
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 417  ←  レコード数

トランザクションエントリは5個、レコード数は417である。1sessionから
インサートをした場合(平均420行)とあまり変わっていない。

では100ブロックづつスキップして見てみる。

ブロックID    トランザクションエントリ数  レコード数
       100                 166               151
       200                 168               110
       300                 169               140

やはりトランザクションエントリの領域がデータ領域を圧迫し、使用率を悪く
している事が分かる。最初のブロックはトランザクションの動き出すタイミン
グにより、200sessionが同時に動いていなかったためであろうと思われる。

そして以下のように、フリーリストからも外れている事も分かった。

(flg: -)
 seg/obj: 0xdbf  csc: 0x00.bf064  itc: 169  flg: -  typ: 2 - INDEX

しかし前回の検証で分かったように、同時にインサートされるということは、
同時に更新される可能性も示唆しているため、これは正しいのかも知れない。
でも普通はINDEXカラムを更新する、特にPKEYなどを更新するのは、論理的に
考えてもよくない場合が多い。

テーブルと同じ扱いで良いのだろうか?という疑問も残る。

次回も引き続きトランザクションエントリに関する検証を行います。

以上、最近ラーメン屋の増えてきた茅ヶ崎にて