リーフ分割検証:意外と増えていたリーフブロック!:おら! オラ! Oracle再検証 @IT出張所(2)(2/4 ページ)
サイジングに頭を悩ませている技術者の皆さん、 インデックスのリーフ分割はどうして発生するのか、知りたくありませんか? 今回はリーフ分割の増え方を徹底的に検証します(編集部)
手順1 まずはデータの作成
では手順1を実行してみましょう。ここでは、10000001から11000000の間で末尾が0の値を10万件作成しています。
SQL> BEGIN 2 FOR i IN 1..100000 LOOP 3 INSERT INTO INDEX_TEST 4 VALUES(10000000 + (i * 10),10000000 + (i * 10),'SCOTT','ENGINEER',9999,SYSDATE,1024,100 ); 5 END LOOP; 6 COMMIT; 7 END; 8 / PL/SQL procedure successfully completed.
上記では末尾が0のデータを10万件挿入しています。この手順のポイントは、EMPNO1とEMPNO2に格納している値を、1ずつではなく10ずつ値を増加させている点です(10000010、10000020、10000030……11000000)。これは、手順2でその間の値を挿入させてリーフ分割を発生させるようにするためです。
SQL> SELECT OBJECT_NAME,OBJECT_ID 2 FROM USER_OBJECTS 3 WHERE OBJECT_NAME In( 'IDX_INDEX_TEST') ; OBJECT_NAME OBJECT_ID -------------------- ---------- IDX_INDEX_TEST 73010 SQL> ALTER SESSION SET EVENTS 'IMMEDIATE TRACE NAME TREEDUMP LEVEL 73010';
TREEDUMPを取得した結果を図にすると、以下のようになります。
リーフブロックの追加
今回実行したプロシージャでは、リーフ分割は発生せず新たなリーフブロックが追加されています。この点について実際に確認してみましょう。
確認は、INSERT文の直後にTREEDUMPを取得するコマンドを実行するように変更して、インデックスのTREEDUMPがどのようになるかその推移を見ます。
SQL> BEGIN 2 FOR i IN 1..100000 LOOP 3 INSERT INTO INDEX_TEST 4 VALUES(10000000 + (i * 10),10000000 + (i * 10),'SCOTT','ENGINEER',9999,SYSDATE,1024,100 ); 5 EXECUTE IMMEDIATE 'ALTER SESSION SET EVENTS ''IMMEDIATE TRACE NAME TREEDUMP LEVEL 73010'''; 6 END LOOP; 7 COMMIT; 8 END; 9 /PL/SQL procedure successfully completed.
トレースファイルが大量に出力されますので、実際に上記を実行するときは件数を絞って実行してください。
----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 1 rrow: 1) ----- end tree dump ----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 2 rrow: 2) ----- end tree dump ----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 3 rrow: 3) ----- end tree dump ----- begin tree dump ・ ・ ・ leaf: 0x2c002a5 46138021 (0: nrow: 105 rrow: 105) ----- end tree dump ----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 106 rrow: 106) ----- end tree dump ----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 107 rrow: 107) ----- end tree dump ----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 108 rrow: 108) ----- end tree dump ----- begin tree dump leaf: 0x2c002a5 46138021 (0: nrow: 109 rrow: 109) ←★Point1 ----- end tree dump ----- begin tree dump branch: 0x2c002a5 46138021 (0: nrow: 2, level: 1) leaf: 0x2c002b7 46138039 (-1: nrow: 109 rrow: 109) leaf: 0x2c002a6 46138022 (0: nrow: 1 rrow: 1) ←★Point2 新規ブロック追加 ----- end tree dump ----- begin tree dump branch: 0x2c002a5 46138021 (0: nrow: 2, level: 1) leaf: 0x2c002b7 46138039 (-1: nrow: 109 rrow: 109) leaf: 0x2c002a6 46138022 (0: nrow: 2 rrow: 2) ----- end tree dump ----- begin tree dump branch: 0x2c002a5 46138021 (0: nrow: 2, level: 1) leaf: 0x2c002b7 46138039 (-1: nrow: 109 rrow: 109) leaf: 0x2c002a6 46138022 (0: nrow: 3 rrow: 3) ----- end tree dump
TREEDUMPを見ると、★Point 1で109行目を格納しており、★Point 2で新たなブロックが追加されています。それぞれのブロックの行数をみると、基のリーフブロックの行数は109行(nrow: 109 rrow: 109)であり、新たに追加されたブロックは1行(nrow: 1 rrow: 1)です。リーフ分割が発生すれば行数が半分に分割されますが、今回のプロシージャではリーフ分割は発生せずにリーフブロックが新たに追加されたということが分かります。
つまり、小さい値から順にブロックに値が格納されていけば、リーフ分割は発生せず、新たなリーフが追加されるということになります。ある意味予想通りの結果といえます。
続いて、手順2を実行しましょう。
Copyright © ITmedia, Inc. All Rights Reserved.