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

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

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

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

先週は200sessionからインサートを行った際にINDEXもテーブル同様、トラン
ザクションエントリが領域を圧迫して、格納効率が悪くなる事を検証した。

テーブルでも行ったが、次はINDEXのmaxtransを2(INDEXは1が指定出来ない)に
して同時トランザクション200からインサートを行い、テーブルの時と同様1ブ
ロックに2レコードも入らない結果となるか検証をしてみたい。

—INDEXにおけるmaxtrans 2—

先週と同じテーブルを使用して、検証を行う。

テーブル作成のDDL

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);

テーブルをtruncateして、前回のINDEXをmaxtrans 2で再作成する。

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

そして先週同様、POPSQLにて作成したプログラムで、200同時sessionより
各1000件、合計20万件のインサートを行う。

遅い・・・
今回は20万件のインサートがずいぶん遅い気がする・・・
結局前回の200同時sessionのときは、7~8分で終わったのが、20分以上も掛か
ってしまった。

ともあれ、終わったのでANALYZEを掛けてみる。

—ANALYZE—

ANALYZE INDEX IDX_TBL_SHU1 COMPUTE STATISTICS;

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

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

あれ?テーブルのときは1ブロックに2レコードも格納されていなかったのに、
INDEXはmaxtrans255のときの結果(1345ブロック)より少ない・・・?

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

先週と同じように3ブロック目と100ブロックづつスキップして見てみる。

ブロックID    トランザクションエントリ数  レコード数
         3                   2               216
       100                   2               231
       200                   2               249
       300                   2               234

---ブロックID 100のダンプの抜粋---

 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   xid:  0x0013.04d.000000e8    uba: 0x0080258f.000e.01  CB--    0  scn 0x0000.000f10bb
0x02   xid:  0x000c.020.000000e9    uba: 0x0080161a.0010.12  --U-    1  fsc 0x0000.000f1114

Leaf block dump
===============
header address 114984028=0x6da845c
kdxcolev 0
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 2
kdxconro 231   ← レコード数

トランザクションエントリの数はmaxtransが2なので、2よりは増えないのは当
然だが、レコード数が比較的均一に格納されている。テーブルの時と違う・・
テーブルと同じように、パフォーマンスを優先させて、トランザクションエン
トリが確保出来ないときは、次のブロックを使うのではないのか?

パフォーマンス・・・
そういえば、今回の検証では20万件インサートするだけで異常に遅かった。
と、いうことはINDEXの場合はトランザクションエントリが確保出来ない場合は
空きが出来るのを待ってから、格納を行うのだろうか?

なぜ?なぜ?・・・

分かった!

1ブロックに1レコードか2レコードしか格納されない場合、INDEXとしての機能
を果たさなくなる恐れがある。例えば1000行程度をselectするレンジスキャン
を行う場合、本来なら数ブロック読み込んで事足りるところが、数百ブロック
のアクセスが必要になってしまう。これではINDEXの本来の目的である、「検索
のパフォーマンスアップ」が意味を為さなくなってしまう。

テーブルの場合も同じ事が言えるかもしれないが、テーブルの本来の目的は
データを格納することであり、「検索の際のパフォーマンス」より「格納の際
のパフォーマンス」を重視した結果であろう。

また、非常に遅くなった原因は今回のINDEXの性格にあった。
通常INDEXは昇順(または降順)に並んでいる。今回のINDEXはTBL_SHU1の
IDカラム(DEFAULT SYSDATE)に作成した。

つまり、インサートされる順番 = ブロック内でINDEXが並ぶ順番になる。
だから常に全てのsessionが同じブロックへ格納を行おうとする。
そのためトランザクションエントリの取り合いになり、パフォーマンスの
低下に繋がったであろうと推測できる。

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

以上、バミューダトライアングルが存在していた茅ヶ崎にて