インデックスに関する検証 その3

<インデックスに関する検証 その3> ペンネーム つけまい

— インデックス利用の落とし穴
レンジ検索で全件検索よりも性能ダウン —

テーブルTEST01には、EMPNO01とEMPNO02という項目があり、それぞれ同じ値が
格納されている。また、EMPNO01にはインデックスを作成している。格納されて
いるデータは、10000010から10単位で増加させ、10100000までの計1万件が格納
されている。

テーブルTEST01

このテーブルに対して、

1. 5000件目のイコール検索

2. ~5000件目までのレンジ検索

をそれぞれEMPNO01(インデックス項目)及びEMPNO02(インデックスなし)を
SELECT文の条件式に用いた結果を以下に示す。

図中の(※2)、(※3)、(※4)は検索する前後に以下のSQL文を発行し、前後の差
分を求めた結果である。

●I/O回数を求めるSQL文

SELECT SUBSTR(A.NAME, INSTRB(A.NAME, '../', -1) + 1, 20) FILE_NAME
,A.STATUS
,TO_CHAR(B.PHYRDS, '99999999999990') PHYRDS
FROM V$DATAFILE A, V$FILESTAT B
WHERE A.FILE# = B.FILE# ;

検索結果で注目していただきたいのが、<検索1>の条件式にインデックス
(EMPNO01)を用いたイコール検索である。「インデックスの構造」でルート、
ブランチ、リーフと、3段階の過程を経て目的とするレコードに到達すると説明
をしたが、この結果ではインデックスのブロックに対してのI/Oは2回しか発生
していない。これは、データが1万件という少ない件数なので、2段階で納まっ
ていることを表している。このことは、以下に示すANALYZEコマンドを用いて確
認することができる。

SQL> ANALYZE INDEX TEST01 VALIDATE STRUCTURE ;
└→ テーブル名ではなくインデックス名
索引が分析されました。

SQL> SELECT HEIGHT,         -- ブランチ・ノードの階層の高さ
2         BLOCKS,         -- 全ブロック数
3         LF_ROWS,        -- リーフ行数
4         LF_BLKS,        -- リーフ・ブロック数
5         BR_ROWS,        -- ブランチ行数
6         BR_BLKS         -- ブランチ・ブロック数
7    FROM INDEX_STATS ;

HEIGHT    BLOCKS   LF_ROWS   LF_BLKS   BR_ROWS   BR_BLKS
--------- --------- --------- --------- --------- ---------
2     51200     10000        87        86         1

上記の結果で注意していただきたいのが、全ブロック数(BLOCKS)である。
51200となっているがリーフ・ブロックとブランチ・ブロックの合計は88になっ
ている。これは、CREATE INDEXでインデックスを作成した際、エクステントを
発生させないためにINITIAL 100Mで領域を確保しているために発生した完全な
未使用ブロック及び、インデックスの「領域管理機構上の問題」であり、「パ
フォーマンスの優先」から生じる未使用ブロックが存在している事を表してい
る。

次に注目していただきたいのが、<検索3>の条件式にインデックス(EMPNO01)
を用いたレンジ検索である。ここでのインデックスに対するI/Oは45回発生して
いる。これは、1件目の値10000010から5000件目の値10050000までが合計44のリ
ーフ・ブロックに格納されており、これにブランチ・ブロックの数1をたした値
である。このことは、次回で紹介するTREEDUMP機能を用いて確認することがで
きる。

初夏 茅ヶ崎にて

~インデックスに関する検証 その3~
by つけまい