Oracle 11g検証 Advanced Compression その9

投稿日: 2008年9月03日

<Oracle 11g検証 Advanced Compression その9>
ペンネーム: クリープ

先週はAdvanced CompressionテーブルにUpdateを実行すると、テーブルのサイ
ズが行移行により拡張する所まで確認しました。
今週はテーブルのダンプを取得して、行移行データがどのように格納されてい
るかを確認し、テーブルのサイズが大きくなった原因を調査することにします。

■■■■■概要■■■■■
1.前回のおさらい
2.ブロックダンプ確認
3.移行先ブロックのダンプ

■環境
RedHat Enterprise Linux ES4 Update 5
Oracle Database 11g Enterprise Edition Release 11.1.0.6 – Production

1.前回のおさらい
先週は通常テーブル、ダイレクト圧縮テーブル、Advanced Compressionテーブ
ルの3テーブルにUpdateを実行して、テーブルのサイズを比較しました。その
結果、ダイレクト圧縮テーブル、Advanced Compressionテーブルのサイズが元
のサイズより大幅に拡張してしまいました。

TABLE_NAME                       Update前(KB) Update後(KB)
------------------------------ -------------- ------------
COMP_TABLE_NORMAL                        2974         2974
COMP_TABLE_DIRECT                        1362         7088
COMP_TABLE_ADVANCED                      1966         7006

これは、圧縮データにUpdateを実行することにより圧縮データが非圧縮データ
になった、ということだけでなく、データが拡張することにより行移行が発生
してしまったことが影響していることがわかりました。

ですが、行移行は1ブロックの行が2ブロックに跨って格納されるので、普通に
考えると2倍程度にしか拡張しないはずです。それでは何故テーブルサイズが
3倍以上に拡張してしまったのでしょうか?
ブロックダンプを確認して、3倍以上に拡張してしまった原因を探ってみるこ
とにしましょう。

2.ブロックダンプ確認
それでは早速、ブロックダンプを取得!

SQL> select segment_name,file_id,block_id,blocks
  2    from dba_extents
  3   where segment_name = 'COMP_TABLE_ADVANCED'
  4     and owner='TEST'
  5     and extent_id=0;

SEGMENT_NAME                      FILE_ID   BLOCK_ID     BLOCKS
------------------------------ ---------- ---------- ----------
COMP_TABLE_ADVANCED                     4       8321         32

SQL> alter system dump datafile 4 block min 8321 block max 8353;

System altered.

ダンプファイルが作成されました。それではダンプファイルを覗いてみましょ
う!

1  block_row_dump:
2  tab 1, row 0, @0x779
3  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
4  col  0: [ 3]  c2 0c 4e
5  col  1: [10]  31 31 31 31 31 31 31 31 31 31
6  bindmp: 2c 00 02 cb c2 0c 4e d2 31 31 31 31 31 31 31 31 31 31
:
:  (省略)
:
7  tab 1, row 19, @0x62c
8  tl: 9 fb: --H----- lb: 0x0  cc: 0
9  nrid:  0x0100326c.0
10  bindmp: 20 00 00 01 00 32 6c 00 00
:
:  (省略)
:
11  tab 1, row 139, @0x1f4
12  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
13  col  0: [ 3]  c2 0e 11
14  col  1: [10]  31 31 31 31 31 31 31 31 31 31
15  bindmp: 2c 00 02 cb c2 0e 11 d2 31 31 31 31 31 31 31 31 31 31
:
:  (省略)
:
16  tab 1, row 146, @0x176
17  tl: 18 fb: --H-FL-- lb: 0x1  cc: 2
18  col  0: [ 3]  c2 0e 18
19  col  1: [10]  31 31 31 31 31 31 31 31 31 31
20  bindmp: 2c 01 02 cb c2 0e 18 d2 31 31 31 31 31 31 31 31 31 31

※同じような構成の行は省略してあります。

上から見ていくと、まず注目すべきは、2行目の「tab 1」。いきなり「tab 1」
になっています。
圧縮テーブルは通常、「tab 0」に圧縮されたデータが格納されていて「tab 1」
に行データが格納されています。

↓圧縮テーブルのダンプは以下参照
https://old.insight-tec.com/mailmagazine/ora3/vol396.html

ところが、今回取得したダンプでは「tab 0」が存在しません。つまりこのブ
ロックは圧縮テーブルの構成にはなっているものの、Updateにより圧縮データ
が非圧縮データになってしまった為、「tab 0」に圧縮された値が格納されな
くなっている、ということのようです。
圧縮されたデータが非圧縮データになっていることは、3行目に「tl: 18」と
あり、圧縮前の18bytesで格納されていることからも確認することができます。

次に7行目(row 19)をご覧下さい。この行から格納パターンがかわっていま
す。そして、9行目には今までのダンプでは見たことのないnridという行が追
加されています。
nridとはnext rowidのことで、行移行先のアドレス情報が格納されています。
ここにある「0x0100326c」ですが、後ろ4桁がブロックIDを表しており、「.0」
はブロックの行番号を表しています。
つまり、326c → 12908となり、ブロックIDが12908の行IDが0にデータが移行
した、ということになります。

では、移行先のデータはどのように格納されているのでしょうか?
きっとここを見れば、テーブルサイズが3倍以上に拡張した原因がわかるはず
です。
ということで、移行先のブロックダンプも取得して中身を確認してみることに
しましょう。

3.移行先ブロックのダンプ
早速、移行先のブロックダンプを取得します。
コマンド実行!

SQL> alter system dump datafile 4 block 12908;

System altered.

これで、nridに記載されたブロックのダンプファイルが作成されました。出力
されたダンプファイルの中身を見てみましょう。

1  block_row_dump:
2  tab 0, row 0, @0x450
3  tl: 24 fb: ----FL-- lb: 0x0  cc: 2
4  hrid: 0x01002085.13
5  col  0: [ 3]  c2 0c 61
6  col  1: [10]  31 31 31 31 31 31 31 31 31 31
7  tab 0, row 1, @0x438
8  tl: 24 fb: ----FL-- lb: 0x0  cc: 2
9  hrid: 0x01002085.14
10  col  0: [ 3]  c2 0c 62
11  col  1: [10]  31 31 31 31 31 31 31 31 31 31
:
:  (省略)
:
12  tab 0, row 33, @0x139
13  tl: 24 fb: ----FL-- lb: 0x0  cc: 2
14  hrid: 0x01002085.34
15  col  0: [ 3]  c2 0d 1e
16  col  1: [10]  31 31 31 31 31 31 31 31 31 31
17  end_of_block_dump

2行目に「tab 0」とあり、最後の行まで「tab 0」が続いています。圧縮され
たデータが格納されていれば、「tab 0」に圧縮データ、「tab 1」に非圧縮デ
ータが格納されているはずです。ということは、このブロックは圧縮データが
格納される構成になっていない、つまり通常のテーブルの構成、ということに
なります。
さすがに行移行先のデータまでは圧縮されないみたいです。

次に3行目をみると「tl: 24」とあり、1行で24bytes格納されていることがわ
かります。
行移行してない行のサイズは18bytesでしたので(元ブロックのダンプ3行目を
参照)、通常時より6bytes余計に格納されていることになります。
では、この6bytesに何が格納されているのでしょうか?

参照元のブロック(データが元々格納されていたブロック)では、格納されて
いる行の情報がbindmpに出力されていたのですが、参照先(行移行先)は通常
テーブルの構成の為bindmpが出力されていません。この為、どのようなデータ
が格納されているかを知ることはできませんが、恐らく、1行下にhrid(head
rowid)という行があり、参照元の情報が出力されていることから、参照元の
ブロックIDと行IDが格納されていると類推できます。

では、この6bytesがテーブルサイズを3倍以上に拡張した要因なのでしょうか?

今回更新したデータ件数は10万件なので、この全ての行で行移行が発生したと
仮定すると、

100000 * 24 = 2400000 ≒ 2343KB

となります。
これを元データの1966KBと足しても合計で4309KBと、Advanced Compressionテ
ーブルのUpdate後のサイズである7006KBとは約2700KB近くの差があることにな
ります。ということはつまり、サイズが拡張してしまう要因は他にもあると考
えられます。

では何が影響しているのでしょうか?

さらにダンプファイルを読み進めていくと12行目に「row 33」とあり、このブ
ロックに34行しか格納されていないことがわかります。(34行となっているの
はrowの番号が0から採番されていている為)
参照元のブロックには147行格納されていたので(参照元ブロックの16行目参
照)、その格納行数が大幅に少なくなってしまっていることがわかります。

ということは、このことがテーブルサイズが3倍以上にも拡張してしまった大
きな要因といえそうです。

では、何故こんなにブロックに格納される行数が少ないのでしょうか?
ブロックの空きを大きめに確保したりしてるのでしょうか?
「avsp」の値を確認してみましょう。

1  data_block_dump,data header at 0x20eb3b94
2  ===============
3  tsiz: 0x468
4  hsiz: 0x56
5  pbl: 0x20eb3b94
6       76543210
7  flag=--------
8  ntab=1
9  nrow=34
10  frre=-1
11  fsbo=0x56
12  fseo=0x139
13  avsp=0xe3
14  tosp=0xe3

上記をみると、avspの値は「0xe3」となっています。「0xe3」は10進数では
227なので、227bytesの空きがあるということになります。
227bytesという空きは、PCTFREEで確保された10%の空き領域とほぼ同じである
ことから、このブロックに新しい行を格納する空き領域はほとんどない状態で
あるといえます。

ですが、このブロックには行データが816bytes(1行当たり24bytesの行が34行)、
ブロックヘッダーが86bytesで、227bytesの空きと合わせると合計1129bytesに
なります。
1ブロックは2048bytesなので、残りの919bytesに通常のブロックにはない何ら
かの情報が格納されており、このことがテーブルサイズが3倍以上に拡張した
大きな要因になっていると考えられます。
では、この919bytesにはどのような情報が格納されているのでしょうか?

疑問を残したままさらに次週に続く。。。

テニスの錦織選手が全米オープンベスト16の快挙!インサイトテニス部もこれ
に続いて。。。!?
恵比寿にて