行移行・行連鎖に関する検証 その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)を長くするような更新をさせてみて、どのよう
に行移行するかを見てみます。
桜が咲き始めたのにやたらと寒い。。。
恵比寿より