行移行・行連鎖に関する検証 その2
<行移行・行連鎖に関する検証 その2>
ペンネーム: ミラニスタ
▼ 前回のおさらい
行移行の発生メカニズムを確認するために、行移行・行連鎖が発生しやすい
環境を準備しました。
具体的には、DB_BLOCK_SIZE=2KB(2048byte)の表領域を作成し、最大レ
コード長が4000byteを超えるテーブルを作成しました。
SQL> SELECT TABLESPACE_NAME,BLOCK_SIZE,INITIAL_EXTENT, 2 EXTENT_MANAGEMENT,ALLOCATION_TYPE,SEGMENT_SPACE_MANAGEMENT 3 FROM DBA_TABLESPACES WHERE TABLESPACE_NAME = 'TS_2K'; TABLESPACE_NAME BLOCK_SIZE INITIAL_EXTENT EXTENT_MAN ALLOCATIO SEGMEN ---------------- ---------- -------------- ---------- --------- ------ TS_2K 2048 10240 LOCAL UNIFORM AUTO SQL> desc SMALL_TBL Name Type ------- --------------- RNO CHAR(16) COL0 VARCHAR2(400) COL1 VARCHAR2(400) COL2 VARCHAR2(400) COL3 VARCHAR2(400) COL4 VARCHAR2(400) COL5 VARCHAR2(400) COL6 VARCHAR2(400) COL7 VARCHAR2(400) COL8 VARCHAR2(400) COL9 VARCHAR2(400)
▼ 1ブロックにぎりぎり収まるように複数レコードをInsertする。
それでは、実際にデータを作って行移行を発生させてみます。
RNO列、COL0~9の11個のカラムにそれぞれ16byteの文字列を以下のSQL文で
10行Insertします。
レコード長は 16*11=176byte+α(レコード・ヘッダ等の長さ)となるので
10行程度であれば、1ブロック(2048byte)にぎりぎり収まるという計算です。
SQL> INSERT INTO SMALL_TBL (RNO,COL0,COL1,COL2,COL3,COL4,COL5,COL6,COL7,COL8,COL9) 2 VALUES ('R'||lpad( '1',15,'0'),lpad('0',16,'0'),lpad('1',16,'1'),lpad('2',16,'2'), 3 lpad('3',16,'3'),lpad('4',16,'4'),lpad('5',16,'5'), 4 lpad('6',16,'6'),lpad('7',16,'7'),lpad('8',16,'8'), 5 lpad('9',16,'9')); 6 INSERT INTO SMALL_TBL (RNO,COL0,COL1,COL2,COL3,COL4,COL5,COL6,COL7,COL8,COL9) 7 VALUES ('R'||lpad( '2',15,'0'),lpad('0',16,'0'),lpad('1',16,'1'),lpad('2',16,'2'), 8 lpad('3',16,'3'),lpad('4',16,'4'),lpad('5',16,'5'), 9 lpad('6',16,'6'),lpad('7',16,'7'),lpad('8',16,'8'), 10 lpad('9',16,'9')); ...................................................................................... 46 INSERT INTO SMALL_TBL (RNO,COL0,COL1,COL2,COL3,COL4,COL5,COL6,COL7,COL8,COL9) 47 VALUES ('R'||lpad('10',15,'0'),lpad('0',16,'0'),lpad('1',16,'1'),lpad('2',16,'2'), 48 lpad('3',16,'3'),lpad('4',16,'4'),lpad('5',16,'5'), 49 lpad('6',16,'6'),lpad('7',16,'7'),lpad('8',16,'8'), 50 lpad('9',16,'9')); 51 COMMIT;
以下のような内容でデータが作成されました。
SQL> SELECT * FROM SMALL_TBL; RNO COL0 COL1 COL2 COL3 ---------------- ---------------- ---------------- ---------------- ---------------- COL4 COL5 COL6 COL7 COL8 ---------------- ---------------- ---------------- ---------------- ---------------- COL9 ---------------- R000000000000001 0000000000000000 1111111111111111 2222222222222222 3333333333333333 4444444444444444 5555555555555555 6666666666666666 7777777777777777 8888888888888888 9999999999999999 R000000000000002 0000000000000000 1111111111111111 2222222222222222 3333333333333333 4444444444444444 5555555555555555 6666666666666666 7777777777777777 8888888888888888 9999999999999999 .................................................................................... R000000000000010 0000000000000000 1111111111111111 2222222222222222 3333333333333333 4444444444444444 5555555555555555 6666666666666666 7777777777777777 8888888888888888 9999999999999999 10 rows selected.
データを作成したので、統計情報を取得して状況を確認してみましょう。
SQL> ANALYZE TABLE SMALL_TBL COMPUTE STATISTICS; Table analyzed. SQL> ANALYZE TABLE SMALL_TBL LIST CHAINED ROWS; Table analyzed. (以後、統計情報を取得するSQL文の実行と結果の表示は割愛します。) SQL> SELECT 2 TABLE_NAME,NUM_ROWS,BLOCKS,EMPTY_BLOCKS 3 ,CHAIN_CNT,AVG_ROW_LEN,TO_CHAR(LAST_ANALYZED,'HH24:MI') LAST_ANALYZED 4 FROM USER_TABLES 5 WHERE TABLE_NAME='SMALL_TBL' TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS CHAIN_CNT AVG_ROW_LEN LAST_ ----------- --------- ------- ------------ ---------- ----------- ----- SMALL_TBL 10 2 3 0 190 18:11
10行作成されていて、行の平均長(全部同じ長さですが)は190byteである
ことがわかります。(もう1行Insertすれば確実に次のブロックに書き込まれ
るでしょう。)
当然ながら、行移行は発生していません。
さらに、以下のSQL文で各行のRowidとどのデータ・ブロックに格納されてい
るかを確認します。(後でブロック・ダンプを見る際に必要な情報です。)
SQL> SELECT 2 ROWID 3 ,DBMS_ROWID.ROWID_TO_ABSOLUTE_FNO(ROWID,'RM','SMALL_TBL') "FILE#" 4 ,DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) "BLOCK#" 5* FROM RM.SMALL_TBL; ROWID FILE# BLOCK# ------------------ ---------- ---------- AAADkVAAFAAAAAHAAA 5 7 AAADkVAAFAAAAAHAAB 5 7 AAADkVAAFAAAAAHAAC 5 7 AAADkVAAFAAAAAHAAD 5 7 AAADkVAAFAAAAAHAAE 5 7 AAADkVAAFAAAAAHAAF 5 7 AAADkVAAFAAAAAHAAG 5 7 AAADkVAAFAAAAAHAAH 5 7 AAADkVAAFAAAAAHAAI 5 7 AAADkVAAFAAAAAHAAJ 5 7 10 rows selected.
すべての行が同じブロックに格納されていることがわかります。
▼ ブロック・ダンプを取得する。
それでは、いよいよブロック・ダンプを取得してブロックの内容を確認して
みましょう。
ブロック・ダンプは次の2通りの方法で取得することができます。
1. ALTER SYSTEM DUMP DATAFILE BLOCK ; 2. ALTER SYSTEM DUMP DATAFILE BLOCK MIN BLOCK MAX ;
ここでは、前者で取得してみましょう。(ダンプはUSER_DUMP_DESTに出力さ
れます。)
SQL> ALTER SYSTEM DUMP DATAFILE 5 BLOCK 7; System altered.
以下が、ブロック・ダンプの内容になります。
この検証環境では、前半がバイナリ(16進)・ダンプ、後半が論理ブロック・
ダンプとなります。(Oracleのバージョンにより異なる場合があります。)
長いので極力必要部分を抜粋し、所々注釈を加えていますので、頑張ってお
付き合いください。
===================================================================== /opt/app/oracle/admin/alcgen/udump/xxxxxx_ora_8652.trc Oracle Database 10g Release 10.2.0.4.0 - 64bit Production ORACLE_HOME = /opt/app/oracle/product/10.2.0/db System name: Linux ............... (中略) ............................................ *** SESSION ID:(446.1507) 2010-03-18 11:18:00.905 Start dump data blocks tsn: 5 file#: 5 minblk 7 maxblk 7 buffer tsn: 5 rdba: 0x01400007 (5/7) scn: 0x0000.0376e690 seq: 0x01 flg: 0x06 tail: 0xe6900601 frmt: 0x02 chkval: 0x1f4b type: 0x06=trans data Hex dump of block: st=0, typ_found=1 ←しばらくバイナリ・ダンプが続く Dump of memory from 0x00000000125CE400 to 0x00000000125CEC00 0125CE400 00006206 01400007 0376E690 06010000 [.b....@...v.....] 0125CE410 00001F4B 00000001 00003915 0376E68F [K........9....v.] ............... (中略) ............................................ 0125CE480 02660324 00EA01A8 0000002C 00000000 [$.f.....,.......] 0125CE490 100B012C 30303052 30303030 30303030 [,...R00000000000] 10行目 0125CE4A0 30313030 30303010 30303030 30303030 [0010.00000000000] 0125CE4B0 30303030 31311030 31313131 31313131 [00000.1111111111] ............... (中略) ............................................ 0125CEB40 3052100B 30303030 30303030 30303030 [..R0000000000000] 1行目 0125CEB50 30103130 30303030 30303030 30303030 [01.0000000000000] 0125CEB60 10303030 31313131 31313131 31313131 [000.111111111111] 0125CEB70 31313131 32323210 32323232 32323232 [1111.22222222222] 0125CEB80 32323232 33331032 33333333 33333333 [22222.3333333333] 0125CEB90 33333333 34103333 34343434 34343434 [333333.444444444] 0125CEBA0 34343434 10343434 35353535 35353535 [4444444.55555555] 0125CEBB0 35353535 35353535 36363610 36363636 [55555555.6666666] 0125CEBC0 36363636 36363636 37371036 37373737 [666666666.777777] 0125CEBD0 37373737 37373737 38103737 38383838 [7777777777.88888] 0125CEBE0 38383838 38383838 10383838 39393939 [88888888888.9999] 0125CEBF0 39393939 39393939 39393939 E6900601 [999999999999....] (行データはブロック内で下から順に格納されるイメージ) ............... (中略) ............................................ data_block_dump,data header at 0x125ce464 =============== tsiz: 0x798 hsiz: 0x26 pbl: 0x125ce464 bdba: 0x01400007 76543210 flag=-------- ntab=1 ←ブロックに格納されている表数 nrow=10 ←ブロックに格納されている行数 frre=-1 fsbo=0x26 fseo=0x2c avsp=0x6 tosp=0x6 0xe:pti[0] nrow=10 offs=0 0x12:pri[0] offs=0x6da ←行情報(ブロック内の行位置) 0x14:pri[1] offs=0x61c pri:pointer record index? 0x16:pri[2] offs=0x55e 1行目(pri[0])~10行目(pri[9]) 0x18:pri[3] offs=0x4a0 行内の相対位置(オフセット)を表示 0x1a:pri[4] offs=0x3e2 0x1c:pri[5] offs=0x324 0x1e:pri[6] offs=0x266 0x20:pri[7] offs=0x1a8 0x22:pri[8] offs=0xea 0x24:pri[9] offs=0x2c block_row_dump: ←論理ダンプの始まり tab 0, row 0, @0x6da tl: 190 fb: --H-FL-- lb: 0x1 cc: 11 ←1行目(長さ190byte) col 0: [16] 52 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31 ←RNO列 col 1: [16] 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 ←COL0列 col 2: [16] 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 31 col 3: [16] 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 32 col 4: [16] 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 33 col 5: [16] 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 col 6: [16] 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 35 col 7: [16] 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 36 col 8: [16] 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 37 col 9: [16] 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 38 col 10: [16] 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 39 ............... (後略) ............................................ =====================================================================
1行目のRNO列
「R 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1」という値は
ASCIIコード(16進数)で
「52 30 30 30 30 30 30 30 30 30 30 30 30 30 30 31」という形として格納
されていることがおわかりでしょうか?
長くなってしまいましたので、今回はここまでです。
次回は、ブロックにぎっしり書き込まれたレコードのちょうど真ん中あたり
の行(RNO=R000000000000005)を長くするような更新をさせてみて、どのよう
に行移行するかを見てみます。
桜が咲き始めたのにやたらと寒い。。。
恵比寿より