Oracle の B*Tree インデックスの内部構造についてお勉強中(その2)

まずは前エントリで書いた Oracle のインデックス構造図解を再掲から。

ora004.png

本題です。Oracle のインデックスの内容をダンプする TreeDump の使い方と解析方法について説明をします。これも定型文なので、覚えておいて損はないかと思います。特にインデックスに関して深追いするなら必須のテクニックです。参考にしたページは下記の2つです。

- スポンサーリンク -

特に株式会社インサイトテクノロジーの記事が秀逸です。この会社の Oracle スキルは尋常じゃぁありませんね。お仕事で見ている DB システムでは、同社が開発している Performance Insight というツールを導入して Oracle を運用管理しているのですが、パフォーマンスチューニング、障害監視など、現場で必要とされる機能をほぼ全て網羅していていて、本当に助かっています。

話がそれました。複合索引の TreeDump の取得についてです。まずはテストテーブルとテストインデックスを作成します。SQL*Plus を起動して、下記の SQL をコピペで実行します。

-- テーブルの作成
CREATE TABLE BTREE_TEST(
  ID   NUMBER,
  NAME VARCHAR2(10)
);

-- インデックスの作成
CREATE INDEX IDX_BTREE_TEST ON BTREE_TEST(ID,NAME);

-- テストデータ作成
BEGIN  
   FOR i IN 1..100 LOOP
      FOR j IN 1..100 LOOP
         INSERT INTO BTREE_TEST VALUES(i,'DATA'||TO_CHAR(j));
      END LOOP;
   END LOOP;
   COMMIT;
END;
/

-- データの確認
SELECT * FROM BTREE_TEST ORDER BY ID, NAME;

TreeDump でインデックスの中身をダンプする手順です。赤文字の部分は各環境に従って変更する部分です。

-- TreeDump で出力されるログファイルの場所確認
SHOW PARAMETERS USER_DUMP_DEST;

-- インデックスの OBJECT_ID を調べる
SELECT OBJECT_ID FROM DBA_OBJECTS WHERE OBJECT_NAME = 'IDX_BTREE_TEST';  

-- 上記 SQL で得られる値で指定した OBJECT_ID のインデックスを TreeDump する
ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME TREEDUMP LEVEL 70550';

これで USER_DUMP_DEST で指定された場所にダンプファイルが生成されています。SID_ora_数値.trc というファイル名で出力されています。ファイルの Timestamp から最新の *.trc が出力されたもののはずです。
ここでは /db/u01/app/oracle/admin/testdb/udump/testdb_ora_30877.trc と仮定して進めます。ファイルを閲覧してみると、下記のような内容になっていると思います。この例では二階層の木構造になっていて、ルートがブランチを兼ねてます。

/db/u01/app/oracle/admin/testdb/udump/testdb_ora_30877.trc
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bit Production
With the Partitioning and Data Mining options
ORACLE_HOME = /db/u01/app/oracle/product/10.2.0/db
System name:	Linux
Node name:	dbsrv01
Release:	2.6.9-78.0.8.ELsmp
Version:	#1 SMP Wed Nov 5 07:14:58 EST 2008
Machine:	x86_64
Instance name: testdb
Redo thread mounted by this instance: 1
Oracle process number: 16
Unix process pid: 30877, image: oracle@dbsrv01 (TNS V1-V3)

*** 2009-11-09 15:00:00.309
*** SERVICE NAME:(SYS$USERS) 2009-11-09 15:00:00.293
*** SESSION ID:(305.6239) 2009-11-09 15:00:00.293
----- begin tree dump
leaf: 0x105aa3d 17148477 (0: nrow: 100 rrow: 100)
----- end tree dump
*** 2009-11-09 15:16:34.379
----- begin tree dump
branch: 0x105aa3d 17148477 (0: nrow: 50, level: 1)
   leaf: 0x105aa4f 17148495 (-1: nrow: 189 rrow: 189)
   leaf: 0x105aa69 17148521 (0: nrow: 189 rrow: 189)
   leaf: 0x105aa5c 17148508 (1: nrow: 189 rrow: 189)
   leaf: 0x105aa76 17148534 (2: nrow: 189 rrow: 189)
   leaf: 0x105aa90 17148560 (3: nrow: 189 rrow: 189)
   leaf: 0x105aa83 17148547 (4: nrow: 189 rrow: 189)
   leaf: 0x105aaaa 17148586 (5: nrow: 189 rrow: 189)
   leaf: 0x105aa9d 17148573 (6: nrow: 189 rrow: 189)
   leaf: 0x105aad1 17148625 (7: nrow: 244 rrow: 244)
   leaf: 0x105aab7 17148599 (8: nrow: 189 rrow: 189)
   leaf: 0x105aac4 17148612 (9: nrow: 189 rrow: 189)
   leaf: 0x105aaeb 17148651 (10: nrow: 189 rrow: 189)
   leaf: 0x105aade 17148638 (11: nrow: 189 rrow: 189)
   leaf: 0x105aa43 17148483 (12: nrow: 244 rrow: 244)
   leaf: 0x105aaf8 17148664 (13: nrow: 189 rrow: 189)
   leaf: 0x105ab05 17148677 (14: nrow: 189 rrow: 189)
   leaf: 0x105aa50 17148496 (15: nrow: 189 rrow: 189)
   leaf: 0x105aa5d 17148509 (16: nrow: 189 rrow: 189)
   leaf: 0x105aa77 17148535 (17: nrow: 244 rrow: 244)
   leaf: 0x105aa6a 17148522 (18: nrow: 189 rrow: 189)
   leaf: 0x105aa84 17148548 (19: nrow: 189 rrow: 189)
   leaf: 0x105aa91 17148561 (20: nrow: 189 rrow: 189)
   leaf: 0x105aa9e 17148574 (21: nrow: 189 rrow: 189)
   leaf: 0x105aab8 17148600 (22: nrow: 244 rrow: 244)
   leaf: 0x105aaab 17148587 (23: nrow: 189 rrow: 189)
   leaf: 0x105aac5 17148613 (24: nrow: 189 rrow: 189)
   leaf: 0x105aad2 17148626 (25: nrow: 189 rrow: 189)
   leaf: 0x105aadf 17148639 (26: nrow: 189 rrow: 189)
   leaf: 0x105aaf9 17148665 (27: nrow: 244 rrow: 244)
   leaf: 0x105aaec 17148652 (28: nrow: 189 rrow: 189)
   leaf: 0x105ab06 17148678 (29: nrow: 189 rrow: 189)
   leaf: 0x105aa44 17148484 (30: nrow: 189 rrow: 189)
   leaf: 0x105aa51 17148497 (31: nrow: 189 rrow: 189)
   leaf: 0x105aa6b 17148523 (32: nrow: 244 rrow: 244)
   leaf: 0x105aa5e 17148510 (33: nrow: 189 rrow: 189)
   leaf: 0x105aa78 17148536 (34: nrow: 189 rrow: 189)
   leaf: 0x105aa85 17148549 (35: nrow: 189 rrow: 189)
   leaf: 0x105aa92 17148562 (36: nrow: 189 rrow: 189)
   leaf: 0x105aaac 17148588 (37: nrow: 244 rrow: 244)
   leaf: 0x105aa9f 17148575 (38: nrow: 189 rrow: 189)
   leaf: 0x105aab9 17148601 (39: nrow: 189 rrow: 189)
   leaf: 0x105aac6 17148614 (40: nrow: 189 rrow: 189)
   leaf: 0x105aad3 17148627 (41: nrow: 189 rrow: 189)
   leaf: 0x105aaed 17148653 (42: nrow: 244 rrow: 244)
   leaf: 0x105aae0 17148640 (43: nrow: 189 rrow: 189)
   leaf: 0x105aafa 17148666 (44: nrow: 189 rrow: 189)
   leaf: 0x105ab07 17148679 (45: nrow: 189 rrow: 189)
   leaf: 0x105aa45 17148485 (46: nrow: 189 rrow: 189)
   leaf: 0x105aa5f 17148511 (47: nrow: 244 rrow: 244)
   leaf: 0x105aa52 17148498 (48: nrow: 244 rrow: 244)
----- end tree dump

部分的に抽出して見てみます。
一行目の意味は、ブランチがアドレス 0x105aa3d (10 進数で 17148477 )のブロックに格納され、このブランチが保持するレコード数(キー数)は nrow=50 個で、level=1 階層目のデータであることを意味しています。
二行目の意味は、リーフ -1 番がアドレス 0x105aa4f (10 進数で 17148495 )のブロックに格納され、このリーフが保持可能なレコード数(データ数)は nrow=189 個で、rrow=189 個のレコードを保持していることを意味しています。ちなみにリーフの番号は何故か -1 から始まります。

branch: 0x105aa3d 17148477 (0: nrow: 50, level: 1)
leaf: 0x105aa4f 17148495 (-1: nrow: 189 rrow: 189)
leaf: 0x105aa69 17148521 (0: nrow: 189 rrow: 189)

実施にはキーに指定したカラムのデータサイズとデータベースのブロックサイズか 1 ブロック内に保持可能なレコード数は計算されるます。その計算に関連してインデックスの領域サイズの見積もりが可能となるのですが、より詳細な情報は OTN Japan - Oracle9i 物理設計:第4部 インデックスの設計 を見ると良いと思います。

さて、次に実際のブランチ、リーフのデータをダンプしたいところですが、すんなりいきません。Oracle のデータ管理が、datafile → tablespace → table/index という階層構造になっており、インデックスのブロックアドレスの物理位置を割り出すには DBMS_UTILITY パッケージを用いる必要があります。DBMS_UTILITY パッケージに取得したいブロックアドレスを指定することで、ファイル ID とブロック番号を知ることができます。

というわけで、下記 SQL を実行してください。赤文字の部分は、それぞれ順にブランチ、リーフ -1 のアドレスを入力します。

SELECT DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(17148477) as "FILE_ID(LEAFBLOCK-1)",
       DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(17148477) as "BLOCK_ID(LEAFBLOCK-1)",
       DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(17148495) as "FILE_ID(LEAFBLOCK0)",
       DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(17148495) as "BLOCK_ID(LEAFBLOCK0)"
FROM dual;

こんなデータが返ってきました。つまり、ファイルID=4でブロック番号=371261 にブランチのデータが格納されています。同様にファイルID=4でブロック番号=371279 にリーフ -1 のデータが格納されています。

FILE_ID(LEAFBLOCK-1) BLOCK_ID(LEAFBLOCK-1) FILE_ID(LEAFBLOCK0) BLOCK_ID(LEAFBLOCK0)
-------------------- --------------------- ------------------- --------------------
                   4                371261                   4               371279

ファイル ID とブロック番号が判明して初めて、指定箇所のデータファイルの内容をダンプすることが可能となります。下記 SQL を実行します。赤文字は適宜変更してください。

-- ブランチのデータをダンプしてみる
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 371261;

-- リーフ -1 のデータをダンプしてみる
ALTER SYSTEM DUMP DATAFILE 4 BLOCK 371279;

先ほどと同じ場所に *.trc が生成されているはずです。もしくは同一ファイルに追記されているはずです。ファイルを開いてみます。ダンプデータの前半はメモリ上のデータのダンプで、後半がデータファイルのダンプになっています。ここでは前半は無視しておきます。

*** 2009-11-09 15:21:41.722
Start dump data blocks tsn: 4 file#: 4 minblk 371261 maxblk 371261
buffer tsn: 4 rdba: 0x0105aa3d (4/371261)
scn: 0x0000.01296dd7 seq: 0x02 flg: 0x04 tail: 0x6dd70602
frmt: 0x02 chkval: 0xeb1e type: 0x06=trans data
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0000000005E85200 to 0x0000000005E87200
005E85200 0000A206 0105AA3D 01296DD7 04020000  [....=....m).....]
005E85210 0000EB1E 00000002 00011397 01296DD7  [.............m).]
005E85220 00000000 00320001 0105AA09 00190008  [......2.........]
005E85230 00002066 00800415 00030FB8 00008000  [f ..............]

・・・中略・・・

005E87190 0509C102 41544144 AA76FE36 C1020105  [....DATA6.v.....]
005E871A0 41440507 FE374154 0105AA5C 0505C102  [..DATA7.\.......]
005E871B0 41544144 AA69FE38 C1020105 41440503  [DATA8.i.......DA]
005E871C0 FE394154 00000000 00000000 00000000  [TA9.............]
005E871D0 00000000 00000000 00000000 00000000  [................]
        Repeat 1 times
005E871F0 00000000 00000000 00000000 6DD70602  [...............m]
Block header dump:  0x0105aa3d
 Object id on Block? Y
 seg/obj: 0x11397  csc: 0x00.1296dd7  itc: 1  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x105aa09 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0008.019.00002066  0x00800415.0fb8.03  C---    0  scn 0x0000.01296dd7
 
Branch block dump
=================
header address 99111500=0x5e8524c
kdxcolev 1
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 1
kdxconro 49
kdxcofbo 126=0x7e
kdxcofeo 7370=0x1cca
kdxcoavs 7244
kdxbrlmc 17148495=0x105aa4f
kdxbrsno 47
kdxbrbksz 8056 
kdxbr2urrc 0
row#0[8042] dba: 17148521=0x105aa69
col 0; len 2; (2):  c1 03
col 1; len 5; (5):  44 41 54 41 39
col 2; TERM
row#1[8028] dba: 17148508=0x105aa5c
col 0; len 2; (2):  c1 05
col 1; len 5; (5):  44 41 54 41 38
col 2; TERM
row#2[8014] dba: 17148534=0x105aa76
col 0; len 2; (2):  c1 07
col 1; len 5; (5):  44 41 54 41 37
col 2; TERM
row#3[8000] dba: 17148560=0x105aa90
col 0; len 2; (2):  c1 09
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#4[7986] dba: 17148547=0x105aa83
col 0; len 2; (2):  c1 0b
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#5[7972] dba: 17148586=0x105aaaa
col 0; len 2; (2):  c1 0d
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#6[7958] dba: 17148573=0x105aa9d
col 0; len 2; (2):  c1 0f
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#7[7930] dba: 17148625=0x105aad1
col 0; len 2; (2):  c1 11
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#8[7944] dba: 17148599=0x105aab7
col 0; len 2; (2):  c1 13
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#9[7916] dba: 17148612=0x105aac4
col 0; len 2; (2):  c1 15
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#10[7902] dba: 17148651=0x105aaeb
col 0; len 2; (2):  c1 17
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#11[7888] dba: 17148638=0x105aade
col 0; len 2; (2):  c1 19
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#12[7860] dba: 17148483=0x105aa43
col 0; len 2; (2):  c1 1b
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#13[7874] dba: 17148664=0x105aaf8
col 0; len 2; (2):  c1 1d
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#14[7846] dba: 17148677=0x105ab05
col 0; len 2; (2):  c1 1f
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#15[7832] dba: 17148496=0x105aa50
col 0; len 2; (2):  c1 21
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#16[7818] dba: 17148509=0x105aa5d
col 0; len 2; (2):  c1 23
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#17[7790] dba: 17148535=0x105aa77
col 0; len 2; (2):  c1 25
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#18[7804] dba: 17148522=0x105aa6a
col 0; len 2; (2):  c1 27
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#19[7776] dba: 17148548=0x105aa84
col 0; len 2; (2):  c1 29
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#20[7762] dba: 17148561=0x105aa91
col 0; len 2; (2):  c1 2b
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#21[7748] dba: 17148574=0x105aa9e
col 0; len 2; (2):  c1 2d
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#22[7720] dba: 17148600=0x105aab8
col 0; len 2; (2):  c1 2f
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#23[7734] dba: 17148587=0x105aaab
col 0; len 2; (2):  c1 31
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#24[7706] dba: 17148613=0x105aac5
col 0; len 2; (2):  c1 33
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#25[7692] dba: 17148626=0x105aad2
col 0; len 2; (2):  c1 35
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#26[7678] dba: 17148639=0x105aadf
col 0; len 2; (2):  c1 37
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#27[7650] dba: 17148665=0x105aaf9
col 0; len 2; (2):  c1 39
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#28[7664] dba: 17148652=0x105aaec
col 0; len 2; (2):  c1 3b
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#29[7636] dba: 17148678=0x105ab06
col 0; len 2; (2):  c1 3d
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#30[7622] dba: 17148484=0x105aa44
col 0; len 2; (2):  c1 3f
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#31[7608] dba: 17148497=0x105aa51
col 0; len 2; (2):  c1 41
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#32[7580] dba: 17148523=0x105aa6b
col 0; len 2; (2):  c1 43
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#33[7594] dba: 17148510=0x105aa5e
col 0; len 2; (2):  c1 45
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#34[7566] dba: 17148536=0x105aa78
col 0; len 2; (2):  c1 47
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#35[7552] dba: 17148549=0x105aa85
col 0; len 2; (2):  c1 49
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#36[7538] dba: 17148562=0x105aa92
col 0; len 2; (2):  c1 4b
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#37[7510] dba: 17148588=0x105aaac
col 0; len 2; (2):  c1 4d
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#38[7524] dba: 17148575=0x105aa9f
col 0; len 2; (2):  c1 4f
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#39[7496] dba: 17148601=0x105aab9
col 0; len 2; (2):  c1 51
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#40[7482] dba: 17148614=0x105aac6
col 0; len 2; (2):  c1 53
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#41[7468] dba: 17148627=0x105aad3
col 0; len 2; (2):  c1 55
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#42[7440] dba: 17148653=0x105aaed
col 0; len 2; (2):  c1 57
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#43[7454] dba: 17148640=0x105aae0
col 0; len 2; (2):  c1 59
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
row#44[7426] dba: 17148666=0x105aafa
col 0; len 2; (2):  c1 5b
col 1; len 5; (5):  44 41 54 41 35
col 2; TERM
row#45[7412] dba: 17148679=0x105ab07
col 0; len 2; (2):  c1 5d
col 1; len 5; (5):  44 41 54 41 34
col 2; TERM
row#46[7398] dba: 17148485=0x105aa45
col 0; len 2; (2):  c1 5f
col 1; len 5; (5):  44 41 54 41 33
col 2; TERM
row#47[7370] dba: 17148511=0x105aa5f
col 0; len 2; (2):  c1 61
col 1; len 5; (5):  44 41 54 41 32
col 2; TERM
row#48[7384] dba: 17148498=0x105aa52
col 0; len 2; (2):  c1 63
col 1; len 5; (5):  44 41 54 41 36
col 2; TERM
----- end of branch block dump -----

データの内部構造を、自分が調べた範囲内で説明します。
kdxbrlmc 17148495=0x105aa4f はリーフ -1 のアドレスを示しています。リーフ -1 は特別扱いなのでしょうか?
row#0[8042] dba: 17148521=0x105aa69 はリーフ 0 のアドレスを示しています。
col 0; len 2; (2): c1 03 は "03" の部分が第一キーの内容になります。実際には -1 された値が格納されていて、数値の "2" を意味しています。
col 1; len 5; (5): 44 41 54 41 39 は第二キーの内容になります。文字列の "DATA9" を意味しています。

つまり、ブランチは ( 2, DATA9 )、( 4, DATA8 )、・・・という木構造になっていることがわかります。 ( 2, DATA9 ) より小さいデータはリーフ -1 で管理し、 ( 2, DATA9 ) 〜 ( 4, DATA8 ) のデータはリーフ 0 で管理。なんて具合です。前エントリで記載したように、複合索引の場合は、キーの個数だけルートとブランチでも管理されていることが証明されました。

Branch block dump
=================
header address 99111500=0x5e8524c
kdxcolev 1
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 1
kdxconro 49
kdxcofbo 126=0x7e
kdxcofeo 7370=0x1cca
kdxcoavs 7244
kdxbrlmc 17148495=0x105aa4f
kdxbrsno 47
kdxbrbksz 8056 
kdxbr2urrc 0
row#0[8042] dba: 17148521=0x105aa69
col 0; len 2; (2):  c1 03
col 1; len 5; (5):  44 41 54 41 39
col 2; TERM
row#1[8028] dba: 17148508=0x105aa5c
col 0; len 2; (2):  c1 05
col 1; len 5; (5):  44 41 54 41 38
col 2; TERM

次にリーフ -1 のブロックのデータを見ています。同じく前半にメモリダンプ、後半にデータファイルのダンプがロギングされます。ここでは後半の数レコードのみ抜粋して記載して説明します。

kdxlenxt 17148521=0x105aa69 は右隣のブロック(リーフ 0)のアドレスを示します。
kdxleprv 0=0x0 は左隣のブロック(リーフ 0)のアドレスを示します。リーフ -1 は左端なので 0x0 なわけです。この2つの値を持ってリーフ間の双方向リストなわけです。
row#0[4456] flag: ----S-, lock: 2, len=18 はリーフ -1 のレコード 0 のヘッダー部分です。
col 0; len 2; (2): c1 02 は第一キーが数値の "1" を意味しています。
col 1; len 5; (5): 44 41 54 41 31 は第二キーが文字列の "DATA1" を意味しています。
col 2; len 6; (6): 01 05 78 4e 00 00 は ROWID の値を意味しています。

Leaf block dump
===============
header address 99111524=0x5e85264
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 1
kdxcoopc 0x87: opcode=7: iot flags=--- is converted=Y
kdxconco 3
kdxcosdc 1
kdxconro 189
kdxcofbo 414=0x19e
kdxcofeo 4456=0x1168
kdxcoavs 4042
kdxlespl 0
kdxlende 0
kdxlenxt 17148521=0x105aa69
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[4456] flag: ----S-, lock: 2, len=18
col 0; len 2; (2):  c1 02
col 1; len 5; (5):  44 41 54 41 31
col 2; len 6; (6):  01 05 78 4e 00 00
row#1[4474] flag: ----S-, lock: 2, len=19
col 0; len 2; (2):  c1 02
col 1; len 6; (6):  44 41 54 41 31 30
col 2; len 6; (6):  01 05 78 4e 00 09

つまり、リーフ -1 では下記のように、ID, NAME, ROWID でソートされた形でデータが格納されていることがわかります。
※ NAME は文字列データなので、DATA1、 DATA10、・・・という順でソートされています。
※ ID, NAME が重複する場合は ROWID でソートされています。

( 1, DATA1 )
( 1, DATA10 )
( 1, DATA100 )
( 1, DATA11 )
( 1, DATA12 )

このリーフは必ずソートされて状態で管理されているがために、データの挿入、更新でリーフ分割によるインデックスのパフォーマンス劣化が発生するわけです。また、この解析からわかるように同一ブロック内もしくは近くのブロック内には第一キーが同じものがかたまって存在します。それゆえ、複合索引の場合は、第一キーのみによる SELECT 文でも、効率よくアクセスが可能( INDEX RANGE SCAN )で、逆に第二キーのみによる SELECT 文では、いくつものブロックを読む( INDEX SKIP SCAN もしくは TABE FULL SCAN )必要がでてくるわけです。

疲れてきたので、その2はここでお終い。その3へ続く。

- スポンサーリンク -

関連する記事&スポンサーリンク