Oracle Database の高度な行圧縮機能を覗いてみた / JPOUG Advent Calendar Day 25
この記事は JPOUG Advent Calendar 2021 25日目の記事です。
24日目はみやくる(@miyacle0R)さんの記事「Azure SQL Database Ledger (Ledger/台帳)と Oracle Blockchain Table を比較してみた話」でした。
25日目は Oracle Advanced Compression の機能のひとつである、高度な行圧縮機能について、実際にブロックレベルでどのように圧縮されているかを確認します。理由はやってみたかったからです。
高度な行圧縮とは
Oracle Advanced Compression の機能のひとつで、OracleDatabase 12c から導入されました。
データ・ブロック内に格納された行データの重複値を排除することで圧縮を実現します。
データ・ブロックの先頭にシンボル表というものがあり、そこにはブロック内の行および列の重複値のコピーが格納されます。そして、ブロック内に存在する重複値はシンボル表を参照する短い値に置き換えられます。
また、挿入や更新の際、即時に圧縮が実行されるわけではなく、ブロック内のデータがデータ・ブロック内部で制御された閾値に達したタイミングで圧縮が実施されます。
参考情報
https://www.oracle.com/technetwork/jp/database/performance/acofaqotn-3861046-ja.pdf https://docs.oracle.com/cd/F19136_01/cncpt/tables-and-table-clusters.html#GUID-54EE5325-0894-4869-B3AD-8912D9B4A329 https://docs.oracle.com/cd/F19136_01/cncpt/logical-storage-structures.html#GUID-B248DC2A-3F65-42CF-ACA5-0B096CFCFC46
非圧縮表のデータ・ブロックを確認してみる
検証用に圧縮設定が有効でない表を作成後、テストデータを挿入し
それが含まれるデータ・ブロック を Block Dump として出力します。
SQL> -- テストユーザー作成 create user test identified by oracle default tablespace users;SQL> 2 3 ユーザーが作成されました。 SQL> grant connect, resource to test; 権限付与が成功しました。 SQL> alter user test quota 256m on users; ユーザーが変更されました。 SQL> -- テストテーブル作成(非圧縮) create table test.disable_compress_tbl ( col1 char(4) , col2 varchar2(15) );SQL> 2 3 4 5 表が作成されました。 SQL> -- 圧縮が有効か確認 col owner format a10 col table_name format a20 col compression format a10 col compress_for format a10 select owner, table_name, compression, compress_for from dba_tables where owner = 'TEST' and table_name = 'DISABLE_COMPRESS_TBL'; SQL> SQL> SQL> SQL> SQL> 2 3 4 5 6 7 8 OWNER TABLE_NAME COMPRESSIO COMPRESS_F ---------- -------------------- ---------- ---------- TEST DISABLE_COMPRESS_TBL DISABLED SQL> -- データ挿入(1000行) begin for i in 1..1000 loop insert into test.disable_compress_tbl(col1, col2) values(i,'MerryChristmas'); end loop; end; / SQL> 2 3 4 5 6 PL/SQLプロシージャが正常に完了しました。 / SQL> -- 統計情報収集 execute DBMS_STATS.GATHER_TABLE_STATS('TEST','DISABLE_COMPRESS_TBL');SQL> PL/SQLプロシージャが正常に完了しました。 SQL> -- テーブルのブロック数を確認 select table_name, avg_space, blocks from dba_tables where owner = 'TEST' and table_name = 'DISABLE_COMPRESS_TBL'; SQL> 2 3 4 5 6 7 TABLE_NAME AVG_SPACE BLOCKS -------------------- ---------- ---------- DISABLE_COMPRESS_TBL 0 5 SQL> -- file_id, block_id を確認 select dbms_rowid.rowid_to_absolute_fno(rowid, 'TEST', 'DISABLE_COMPRESS_TBL') file_id, dbms_rowid.rowid_block_number(rowid) block_id from test.disable_compress_tbl where col1 = 1; SQL> 2 3 4 5 FILE_ID BLOCK_ID ---------- ---------- 4 134 SQL> -- block dump を出力 alter system dump datafile 4 block 134; SQL> システムが変更されました。 [oracle@oracledev trace]$ ls -lrt 合計 11588 : -rw-r-----. 1 oracle oinstall 555487 12月 25 11:06 2021 alert_orcl.log -rw-r-----. 1 oracle oinstall 1073 12月 25 11:07 2021 orcl_ora_3117.trm -rw-r-----. 1 oracle oinstall 83280 12月 25 11:07 2021 orcl_ora_3117.trc <--★Block Dump :
上記で出力した、非圧縮表の Block Dump の内容を確認します。 (1行目~3行目の格納データを抜粋)
▼orcl_ora_3117.trc : block_row_dump: tab 0, row 0, @0x1f81 ★(1) tl: 23 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [ 4] 31 20 20 20 col 1: [14] 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 ★(2) tab 0, row 1, @0x1f6a tl: 23 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [ 4] 32 20 20 20 col 1: [14] 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 tab 0, row 2, @0x1f53 tl: 23 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [ 4] 33 20 20 20 col 1: [14] 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 :
★(1)~★(2)の4行が、ひとつの行の情報です。
それぞれの項目は下記です。(確認できた項目のみ記載しています)
・tab 0 : テーブル番号
・row : 行番号
・tl : メタデータを含む行の長さ
・cc : カラムの数
たとえば★(2)行のデータであれば、
col 1(2番目のカラム)のカラム長は 14 byte で
格納されているデータはASCIIで "4d 65 72 72 79 43 68 72 69 73 74 6d 61 73" です。
変換すると "MerryChristmas" となります。
今回検証で使用するデータ・ブロック内の col 1 のデータはすべて同じのため
★(2)行と同値のデータが2行目、3行目...と続いています。
高度な行圧縮が有効な表のデータ・ブロックを確認してみる
非圧縮表と同様に、検証用の表を作成後 Block Dump を出力し、中身を確認します。
-- テストテーブル作成(高度な行圧縮が有効) SQL> create table test.enable_compress_tbl ( col1 char(4) , col2 varchar2(15) )row store compress advanced; 2 3 4 5 表が作成されました。 SQL> -- 圧縮が有効か確認 col owner format a10 col table_name format a20 col compression format a10 col compress_for format a10 select owner, table_name, compression, compress_for from dba_tables where owner = 'TEST' and table_name = 'ENABLE_COMPRESS_TBL';SQL> SQL> SQL> SQL> SQL> 2 3 4 5 6 7 8 OWNER TABLE_NAME COMPRESSIO COMPRESS_F ---------- -------------------- ---------- ---------- TEST ENABLE_COMPRESS_TBL ENABLED ADVANCED SQL> -- データ挿入(1000行) begin for i in 1..1000 loop insert into test.enable_compress_tbl(col1, col2) values(i,'MerryChristmas'); end loop; end; /SQL> 2 3 4 5 6 PL/SQLプロシージャが正常に完了しました。 SQL> -- 統計情報収集 execute DBMS_STATS.GATHER_TABLE_STATS('TEST','ENABLE_COMPRESS_TBL');SQL> PL/SQLプロシージャが正常に完了しました。 SQL> -- テーブルのブロック数を確認 select table_name, avg_space, blocks from dba_tables where owner = 'TEST' and table_name = 'ENABLE_COMPRESS_TBL';SQL> 2 3 4 5 6 7 TABLE_NAME AVG_SPACE BLOCKS -------------------- ---------- ---------- ENABLE_COMPRESS_TBL 0 5 SQL> -- file_id, block_id を確認 select dbms_rowid.rowid_to_absolute_fno(rowid, 'TEST', 'ENABLE_COMPRESS_TBL') file_id, dbms_rowid.rowid_block_number(rowid) block_id from test.enable_compress_tbl where col1 = 1; SQL> 2 3 4 5 FILE_ID BLOCK_ID ---------- ---------- 4 142 SQL> -- block dump を出力 alter system dump datafile 4 block 142;SQL> システムが変更されました。 [oracle@oracledev ~]$ ls -lrt /u01/app/oracle/diag/rdbms/orcl/orcl/trace/ : -rw-r-----. 1 oracle oinstall 1051 12月 25 15:47 2021 orcl_ora_3610.trm -rw-r-----. 1 oracle oinstall 163759 12月 25 15:47 2021 orcl_ora_3610.trc ★ -rw-r-----. 1 oracle oinstall 4692 12月 25 15:48 2021 orcl_mmon_3163.trm -rw-r-----. 1 oracle oinstall 26219 12月 25 15:48 2021 orcl_mmon_3163.trc -rw-r-----. 1 oracle oinstall 4668 12月 25 15:48 2021 orcl_gen0_3115.trm -rw-r-----. 1 oracle oinstall 26009 12月 25 15:48 2021 orcl_gen0_3115.trc
上記で出力した Block Dump の内容を確認します。(1行目~3行目の格納データを抜粋)
▼orcl_ora_3610.trc : block_row_dump: tab 0, row 0, @0x1f87 tl: 17 fb: --H-FL-- lb: 0x0 cc: 1 col 0: [14] 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 ★(3) bindmp: 02 4c d6 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 tab 1, row 0, @0x1f7e tl: 9 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [ 4] 31 20 20 20 col 1: [14] 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 ★(4) bindmp: 2c 01 02 cc 31 20 20 20 00 tab 1, row 1, @0x1f75 tl: 9 fb: --H-FL-- lb: 0x1 cc: 2 col 0: [ 4] 32 20 20 20 col 1: [14] 4d 65 72 72 79 43 68 72 69 73 74 6d 61 73 bindmp: 2c 01 02 cc 32 20 20 20 00 :
※非圧縮表確認時に説明した項目については割愛します。
まず、★(3)の行で tab 0 のテーブルが、ひとつの列値(col 0)だけデータを持っていることが確認できます。 この tab 0 はシンボル表です。この中に、ブロック内の行および列の重複値のコピーが格納されます。 また、非圧縮表と異なり、bindmp という項目があります。これは圧縮された行データを示します。
なお、tab 1, row 0 以降から、シンボル表ではない、挿入した行データの情報となります。
下記に、今回出力された★(4)の bindmp の値と位置を記載します。
※4~8に格納された値の意味についてはわかりませんでした。
値の位置: 1 2 3 4 5 6 7 8 9 ──────────────────────────────────── bindmp: 2c 01 02 cc 32 20 20 20 00
- 1~3: 行のヘッダー情報
- 4~8: 不明(5番目の値は1ずつ増加しているので行番号?)
- 9 : シンボル表への参照を示します。(00 は tab 0, row 0 を参照している。)
なお、参照先 tab 0, row 0 は "4d 65 72 72 79 43 68 72 69 73 74 6d 61 73" となっており、 "MerryChristmas" が格納されています。
追加で確認
非圧縮表、高度な行圧縮が有効な表にて検証で挿入したデータが少なかったためか
使用ブロック数に差が出ませんでした。
なので、両方に9000行ほど追加して、使用するブロック数に差が出るか確認しました。
SQL> begin for i in 1001..9999 loop insert into test.disable_compress_tbl(col1, col2) values(i,'MerryChristmas'); end loop; end; / 2 3 4 5 6 PL/SQLプロシージャが正常に完了しました。 SQL> begin for i in 1001..9999 loop insert into test.enable_compress_tbl(col1, col2) values(i,'MerryChristmas'); end loop; end; / 2 3 4 5 6 PL/SQLプロシージャが正常に完了しました。 SQL> -- 統計情報収集 execute DBMS_STATS.GATHER_TABLE_STATS('TEST','DISABLE_COMPRESS_TBL');SQL> PL/SQLプロシージャが正常に完了しました。 SQL> -- 統計情報収集 execute DBMS_STATS.GATHER_TABLE_STATS('TEST','ENABLE_COMPRESS_TBL');SQL> PL/SQLプロシージャが正常に完了しました。 SQL> -- テーブルのブロック数を確認 select table_name, avg_space, blocks from dba_tables where owner = 'TEST' and table_name = 'DISABLE_COMPRESS_TBL';SQL> 2 3 4 5 6 7 TABLE_NAME AVG_SPACE BLOCKS ----------------------------------- ---------- ---------- DISABLE_COMPRESS_TBL 0 35 ★非圧縮表 SQL> -- テーブルのブロック数を確認 select table_name, avg_space, blocks from dba_tables where owner = 'TEST' and table_name = 'ENABLE_COMPRESS_TBL';SQL> 2 3 4 5 6 7 TABLE_NAME AVG_SPACE BLOCKS ----------------------------------- ---------- ---------- ENABLE_COMPRESS_TBL 0 20 ★高度な行圧縮が有効な表
高度な行圧縮が有効な表では、使用ブロック数が少ない事を確認できました。
まとめ
高度な行圧縮について、データ・ブロック内で行データの重複値のコピーをシンボル表に格納している事が確認できました。
また、データ・ブロック内に存在する圧縮された行データについて、シンボル表を参照する短い値に置き換わる事を確認できました。
高度な行圧縮を有効にした場合、使用するブロック数が少なく済む事が確認できました。
主な参考情報
Block Dump の出力や内容の確認方法については、下記エントリを参考にしました。
Oracle Database のデータ・ブロックのダンプとその解析 - ぱと隊長日誌
また、シンボル表や bindmp の確認については、下記エントリを参考にしました。
Oracle 11g検証 Advanced Compression その4 - InsightTechnology 旧ブログ
Oracle 11g検証 Advanced Compression その5 - InsightTechnology 旧ブログ
Oracle 11g検証 Advanced Compression その6 - InsightTechnology 旧ブログ
最後に
ノリと勢いで登録してしまった人生で初めての Advent Calendar でしたが
適度なプレッシャーがあり、書いていて楽しかったです。
もうクリスマスは終わりそうですが(現在 12/25 22:44)
みなさま、よいクリスマス&よいお年を!
(また来年も書きたーい!)