Oracle 11g検証 Advanced Compression その4

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

先週はダイレクト圧縮よりもAdvanced Compressionで圧縮したテーブルの方が
サイズが大きくなってしまうという点について述べました。

両者のブロック・ダンプを比較した結果、Advanced Compressionはダイレクト
圧縮よりも 1ブロック当たりに格納する行数が少ないというところまではわか
ったのですが、では、なぜ行数に違いが出るのでしょうか?

今週と来週にかけて、この点について見ていきたいと思います。

■■■■■概要■■■■■
1.通常テーブルのブロック・ダンプ解析
2.ダイレクト圧縮テーブルのブロック・ダンプ解析
3.Advanced Compressionテーブルのブロック・ダンプ解析(来週)

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

1.通常テーブルのブロック・ダンプ解析
最初に通常テーブルに格納されている行データを解析します。その後でダイレ
クト圧縮テーブルとAdvanced Compressionテーブルについても解析し、最後に
それらの結果を見比べながら、 1ブロック当たりの行数が異なる点について明
らかにしていきます。

ということで、まずは通常テーブルのブロック・ダンプを解析!

・通常テーブルのブロック・ダンプ

     1  block_row_dump:
     2  tab 0, row 0, @0x786
     3  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
     4  col  0: [ 3]  c2 18 1e
     5  col  1: [10]  30 30 30 30 30 30 30 30 30 30
     6  tab 0, row 1, @0x774
     7  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
     8  col  0: [ 3]  c2 18 1f
     9  col  1: [10]  30 30 30 30 30 30 30 30 30 30
    10  tab 0, row 2, @0x762
    11  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
    12  col  0: [ 3]  c2 18 20
    13  col  1: [10]  30 30 30 30 30 30 30 30 30 30
     :
     :  (省略)
     :
    14  tab 0, row 84, @0x19f
    15  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
    16  col  0: [ 3]  c2 19 0e
    17  col  1: [10]  30 30 30 30 30 30 30 30 30 30
    18  tab 0, row 85, @0x18d
    19  tl: 18 fb: --H-FL-- lb: 0x0  cc: 2
    20  col  0: [ 3]  c2 19 0f
    21  col  1: [10]  30 30 30 30 30 30 30 30 30 30
    22  end_of_block_dump

2~5行目と6~9行目で似たような構成になっており、全部で86のまとまりにな
っています。
前回の検証で通常テーブルは1ブロックに86行格納されていたことから、この
4行ごとのまとまりがテーブルデータの1行に相当しています。

このまとまりについてもう少し詳しく見てみることにしましょう。

2行目の「row 0」は、その後の6行目、10行目でそれぞれ「row 1」、「row 2」
と1つずつカウントアップしており、最後(18行目)に「row 85」となってい
ます。

     2  tab 0, row 0, @0x786
     :  (省略)
     6  tab 0, row 1, @0x774
     :  (省略)
    10  tab 0, row 2, @0x762
     :
     :  (省略)
     :
    18  tab 0, row 85, @0x18d

これはつまり、ブロックに格納されている行の番号と類推できます。
(行番号が「0」から始まっている為、最後が85になっています。)

そして、3行目の「tl: 18」は1行のバイト長(total length)、「cc: 2」は
カラムの数(Column Count)、4行目、5行目の「col 0」、「col 1」はそれ
ぞれ1カラム目(SEQ_NO)、2カラム目(MSG)を表しています。

また、[ 3]、[10]とあるのは各カラムのバイト長で、その右に記載されている
のが実際に格納されているデータになります。
ここでお気づきになった読者の方もいるかと思いますが、各カラムのバイト長
を合計すると3 + 10 = 13bytesで「tl」の18bytesにはなりません。
何故このような差が発生するのかというと、「tl」の値にはデータとは別に行
に関する情報が5bytes加算されている為です。
ここでいう行に関する情報とは、行ヘッダー情報と列の長さに関する情報のこ
とです。これについてはマニュアルに以下の記載があります。

▼Oracle Database 概要(11gリリース1)より

======================================================================
1 つのブロックに完全に収まる行は、最低3 バイトの行ヘッダーを持っていま
す。各行は、行ヘッダー情報の後に列の長さとデータを格納します。列の長さ
は、250 バイト以下のデータを格納する列については1 バイト、250 バイトよ
りも大きなデータを格納する列については3 バイトを必要とし、列データの直
前に位置します。
======================================================================

つまり、行ヘッダーで3bytes、列の長さで2bytes(1byte * 2カラム)で合計
5bytesが行に関する情報として格納されています。これにカラムのバイト長の
13bytesを加算して18bytesという「tl」の値になります。

    ・1行当たりのバイト長
      行ヘッダー情報のサイズ               3バイト
      列の長さ                             2バイト
       1番目のカラム(SEQ_NO)のバイト長     3バイト
    +  2番目のカラム( MSG)のバイト長      10バイト
    -----------------------------------------------
                                          18バイト

※SEQ_NOは値によってサイズが変わる為、3bytesより大きくなる行も存在しま
す。

1行が18bytesで、86行がこのブロックに格納されている為、18bytes * 86行で合
計1548bytesが1ブロックに格納されていたということになります。

2.ダイレクト圧縮テーブルのブロック・ダンプ解析
では、同様にダイレクト圧縮テーブルについても見ていきましょう。

・ダイレクト圧縮テーブルのブロック・ダンプ

     1  block_row_dump:
     2  tab 0, row 0, @0x773
     3  tl: 13 fb: --H-FL-- lb: 0x0  cc: 1
     4  col  0: [10]  30 30 30 30 30 30 30 30 30 30
     5  bindmp: 00 a8 d2 30 30 30 30 30 30 30 30 30 30
     6  tab 1, row 0, @0x76a
     7  tl: 9 fb: --H-FL-- lb: 0x0  cc: 2
     8  col  0: [10]  30 30 30 30 30 30 30 30 30 30
     9  col  1: [ 3]  c2 18 1e
    10  bindmp: 2c 00 02 01 00 cb c2 18 1e
    11  tab 1, row 1, @0x761
    12  tl: 9 fb: --H-FL-- lb: 0x0  cc: 2
    13  col  0: [10]  30 30 30 30 30 30 30 30 30 30
    14  col  1: [ 3]  c2 18 1f
    15  bindmp: 2c 00 02 01 00 cb c2 18 1f
    16  tab 1, row 2, @0x758
    17  tl: 9 fb: --H-FL-- lb: 0x0  cc: 2
    18  col  0: [10]  30 30 30 30 30 30 30 30 30 30
    19  col  1: [ 3]  c2 18 20
    20  bindmp: 2c 00 02 01 00 cb c2 18 20
     :
     :  (省略)
     :
    21  tab 1, row 166, @0x196
    22  tl: 9 fb: --H-FL-- lb: 0x0  cc: 2
    23  col  0: [10]  30 30 30 30 30 30 30 30 30 30
    24  col  1: [ 3]  c2 0f 40
    25  bindmp: 2c 00 02 01 00 cb c2 0f 40
    26  tab 1, row 167, @0x18d
    27  tl: 9 fb: --H-FL-- lb: 0x0  cc: 2
    28  col  0: [10]  30 30 30 30 30 30 30 30 30 30
    29  col  1: [ 3]  c2 0f 41
    30  bindmp: 2c 00 02 01 00 cb c2 0f 41
    31  end_of_block_dump

2行目と6行目に「row 0」という項目が2つあり、2行目は「tab 0」、6行目は
「tab 1」となっています。
これは、テーブルが2つあるということになります。でも、このブロックには
1テーブルの情報しか格納されてないはず!?
っと、そういえばこのメルマガの第1回でセグメント圧縮に関する以下のよう
な記述がありました。

▼Oracle9i リリース2:データ・セグメントの圧縮 オラクル・ホワイト・ペ
ーパーより

======================================================================
Oracle9i リリース2 では、データベース・ブロック内でのデータの重複値を
取り除くことでデータを圧縮します。各データベース・ブロック(ディスク・
ページ)に格納された圧縮データは、それぞれ独立しています。つまり、ある
ブロック内において非圧縮データを再作成するために必要な情報はすべてその
ブロック内にあります。ブロック内のすべての行および列の重複値は、まず1 
度ブロックの先頭ののシンボル表と呼ばれる場所に格納されます。そしてそれ
らの重複値は、シンボル表への短い参照に置き換えられます。
======================================================================

↓詳しくは、Advanced Compression その1を参照
http://www.insight-tec.com/mailmagazine/ora3/vol392.html

ここにはシンボル表、という言葉が使われています。
つまり、このブロックに格納されているテーブルとは、圧縮データを格納するシ
ンボル表と行データを格納する表のことで、これを「tab」という項目で論理的
に分けて管理している、ということがわかります。

この「tab 0」というシンボル表の「col 0」には、MSGカラムに格納されている
値「30 30 30 30 30 30 30 30 30 30」が記載されています。
これは、「30 30 30 30 30 30 30 30 30 30(実際の値:0000000000)」という
重複値が「tab 0」というシンボル表に格納されているということで、この値を
各行が参照している、といえます。

では、圧縮された各行はブロック内でどのように格納されているのでしょうか?
7行目の「tl」の値を見ると9になっていることから、通常テーブルの18よりもサ
イズが小さい為、圧縮されていることがわかります。
ダイレクト圧縮テーブルのダンプを見ると、通常テーブルにはなかったbindmp
(binary dump)という行があり、恐らく、この行を見れば圧縮された行がどの
ように格納されているかわかりそうです。

ではbindumpについて解析。。。は長くなりそうなので来週にすることにします。
来週は、bindmpについてと、今週できなかったAdvanced Compressionテーブルの
解析をしていきましょう。

学生が夏休みで、朝の通勤が少し楽になった気がします。
恵比寿にて