しばちょう先生の試して納得!DBAへの道 indexページ▶▶
みなさん、こんにちは。”しばちょう”こと柴田長(しばた つかさ)です。過ごし易い季節になってきましたねーと、気付けば今年もすでに10月へ突入するらしいですが、まだまだ皆様をアツくするホットなイベントをご紹介させて頂きます。

2015年10月17日(土)、Japan Oracle User Group(JPOUG)主催の大規模イベントJPOUG> SET EVENTS 20151017 が開催されます。熟練した技術者から まったくの初心者まで全員が楽しめる Oracle Databaseを中心としたデータベース関連の話題を扱う様々なセッションを通じて みんなが交流します。技術者の交流の場に興味のある方はWebからのお申込みの上、ぜひご参加ください。私も参加予定です!
さて今回もOracle Database 12cから登場した新機能を体験して頂きます。思い返してみてください。この連載の中でも何度か「圧縮」についてはご紹介させて頂いてきましたが「表の圧 縮」しか扱ってきませんでしたよね。ところで「索引の圧縮」は無いの?とお気付きの方もいらっしゃったかと思います。と言う事で、お待たせ致 しました!! Oracle Database 12cから登場した『拡張索引圧縮(Advanced Index Compression)』を今回は試してみたいと思います。もちろん、従来からの索引圧縮機能である「接頭辞圧縮(プリフィックス圧縮 / キー圧縮)」が存在していたことをご存知の方もいらっしゃるかと思いますが、12cのマニュアルには「拡張索引圧縮(Advanced Index Compression)」はその「接頭辞圧縮(キー圧縮)」を改善したものとの記載もあります。可能な範囲で使い方をご紹介出来ればと考えて おりますので、是非ともお付き合い下さい。ちなみに、「拡張索引圧縮(Advanced Index Compression)」はAdvanced Compression オプションに含まれる機能ですのでご注意ください。
以下の演習をOracle Database 12c Release 1 (12.1.0.2) 以降のデータベースで試してみてください。
なお、Oracle Database 12c Release 1 (12.1.0.2) の単一インスタンス・データベースのインストレーション・ガイド 及び、Oracle VM VirtualBoxを用いたOracle Database 12c Release 1 環境の構築ガイドが、Oracle Technology Networkのこちらのページに公開されておりますので、参考にしてみてください。
【参考情報】
[Oracle Advanced Compression] http://www.oracle.com/technetwork/jp/database/options/compression/overview/index.html
[White Paper] Oracle Database 12cのOracle Advanced Compression 新機能概要
- 【今回ご紹介するネタ一覧(逆引き)】
- ✓ 主キーに対する拡張索引圧縮の有効化の制約(演習2)
- ✓ B*Tree索引のリーフブロック数の確認方法(演習3)
- ✓ 任意の索引に対して拡張索引圧縮を有効化した場合の圧縮率の見積もり方法(演習4)
- ✓ 非圧縮な索引に対して拡張索引圧縮を有効化する方法(演習5)
- ✓ 任意の表に作成されている全索引に対して拡張索引圧縮を有効化した場合の圧縮率の見積もり方法(演習8)
1. 次のSQLを実行し、2GBの表領域TBS42とその表領域をデフォルト表領域とする検証用スキーマTRYを作成して下さい。さらに、検証用の表TAB42を作成し、1,000,000レコードをINSERTして下さい。
$ sqlplus /nolog
SLQ>
connect / as sysdba
create tablespace TBS42 datafile '+FRA(DATAFILE)' size 2g ;
create user TRY identified by TRY12345 default tablespace TBS42 ;
alter user TRY quota unlimited on TBS42 ;
grant CONNECT, RESOURCE to TRY ;
connect TRY/TRY12345
create table TAB42 (COL1 number,
COL2 date,
COL3 varchar2(100),
COL4 varchar2(100),
COL5 varchar2(100)) ;
-- 1,000,000 rows created.
insert /*+append */ into TAB42 select LEVEL
, to_date('2015/09/25', 'YYYY/MM/DD') + mod(LEVEL, 12*5)
, rpad('sibacho', 100, '*')
, rpad('sibacho'||to_char(mod(LEVEL, 1000)), 100, '*')
, rpad('sibacho'||to_char(mod(LEVEL,10000)), 100, '*')
from DUAL connect by LEVEL <= 1000000 ;
commit ;
-- Segmeng Size
set linesize 150 pages 5000
col SEGMENT_NAME for a20
select SEGMENT_NAME, SEGMENT_TYPE, BLOCKS, BYTES/1024/1024
from USER_SEGMENTS order by 2 DESC, 1 ASC ;
SEGMENT_NAME SEGMENT_TYPE BLOCKS BYTES/1024/1024
-------------------- ------------------ ---------- ---------------
TAB42 TABLE 46080 360
はいー、毎度お馴染みの検証環境の作成ですね。特に問題は無いかと思います。第一カラムはNUMBER型、第二カラムはDATE型、第三、第四、第五カラムはVARCHAR2型です。特に把握しておくべきは、第三、第四、第五カラムの列データ長は全て100バイトであり、mod関数を使用してカーディナリティを調整している点に注意して下さいね。
また、先にお断りしておきますが、本連載で扱う表やレコード(カーディナリティ)は検証目的で作成したものです。その為、以降の演習の中で記載されている圧縮率についてはお客様の本番環境でも同じ結果となることを保証している訳ではなく、あくまで参考情報としてお取り扱い下さい。
さあ、張り切って行きましょう!!
2. 表TAB42に対して、列COL1を含む主キーを作成して下さい。ただし、主キーを構成する索引には拡張索引圧縮を指定して下さい。
$ sqlplus /nolog SQL> connect TRY/TRY12345 -- Error : ORA-25193 alter table TAB42 add constraint PK_TAB42_COL1 primary key (COL1) using index compress advanced low ; ERROR at line 1: ORA-25193: cannot use COMPRESS option for a single column key -- Error : ORA-25193 create unique index PK_TAB42_COL1 on TAB42(COL1) compress advanced low ; ERROR at line 1: ORA-25193: cannot use COMPRESS option for a single column key
上記の回答例の通り、えー!!となった方、ありがとうございますm(_ _)m イキナリ出鼻をくじかれた形ですね。イイですねー、こういう事が新機能検証のだいご味なのでしょう。ワクワクします。
まずは、SQL文の構文が正しいのかを「Oracle Database SQL言語リファレンス 12cリリース1 (12.1)」で確認してみましょう。
[ALTER TABLE] をまずは参照し、主キー制約に関する句となりますから、 [constraint_clauses::=] へ移動します。続いて、制約を「追加」することから[ADD]を辿ることで [out_of_line_constraint::=] を参照したくなりますね。 主キーですから[PRIMARY KEY] を辿ると[constraint_state::=] に辿りつきます。が、ここから少し悩むかもしれませんね。ここでは[using_index_clause ::=] を辿り、圧縮は索引の属性であることから[index_attributes::=]へ行くと・・・、やっと圧縮(compression)というキーワードが見えてきましたね。[index_compressoin::=]では、従来のプリフィックス圧縮(prefix_compression)と拡張索引圧縮(advanced_index_compression)のどちらかを選択できるようです。と言う事で長かったですが、上記回答例の一つ目のalter table文は構文的には間違っていないと言う事が分かります。
では、何故、ORA-25193エラーが発生してしまったのでしょうか?と言う事で、さらに[advanced_index_compression::=]のリンクを辿ってみると次のような記述が表示されます。おっとー、このような制限事項が存在することに充分注意しましょう。
COMPRESS ADVANCED LOWを指定して、advanced index compressionを有効化します。拡張索引圧縮では、索引の効率的なアクセスを維持しながら圧縮率を大幅に向上します。このため、拡張索引圧縮は、接頭辞圧縮の適切な候補ではない索引を含むすべてのサポートされている索引で正常に動作します。
索引圧縮の制限事項 次の制限事項は、索引圧縮に適用されます。
✓ ビットマップ索引または単一列の一意の索引に接頭辞圧縮または拡張索引圧縮は指定できません。
✓ 索引構成表に拡張索引圧縮を指定できません。
と言う事だったので、演習問題を見直してみてください。はい、気付かれましたよね。私は「列COL1を含む主キーを作成して」と書いてありますよね。列COL1のみで主キーを作成して下さい。とは言っていませんから、気を取り直して、COL2列も含めた複合索引として主キーを作成してみましょう。
$ sqlplus /nolog SQL> connect TRY/TRY12345 -- Success alter table TAB42 add constraint PK_TAB42_COL2_1 primary key (COL2, COL1) using index compress advanced low ; Index created. set linesize 150 pages 5000 col INDEX_NAME for a20 select INDEX_NAME, INDEX_TYPE, COMPRESSION from USER_INDEXES order by 1 ; INDEX_NAME INDEX_TYPE COMPRESSION -------------------- --------------------------- ------------- PK_TAB42_COL2_1 NORMAL ADVANCED LOW
USER_INDEXESビューのCOMPRESSION列に「ADVANCED LOW」と表示されていますので、無事に拡張索引圧縮が有効化された主キーが作成されたことが確認出来ましたね。
3. 表TAB42の列COL3に対して非圧縮なB*Tree索引を作成し、その索引のリーフブロック数を確認してください。
$ sqlplus /nolog
SQL> connect TRY/TRY12345
create index IDX_TAB42_COL3 on TAB42(COL3) nocompress ;
set linesize 150 pages 5000
col INDEX_NAME for a20
select INDEX_NAME, INDEX_TYPE, COMPRESSION, LEAF_BLOCKS
from USER_INDEXES order by 2 ;
INDEX_NAME INDEX_TYPE COMPRESSION LEAF_BLOCKS
-------------------- ----------------- ------------- -----------
PK_TAB42_COL2_1 NORMAL ADVANCED LOW 2094
IDX_TAB42_COL3 NORMAL DISABLED 15625
はい、こちらは簡単ですよね。上記回答例では、create index文に「nocompress」オプションを指定していますが、指定しなくても非圧縮となります。さあ、次に行きましょう。
4. 演習3で作成した索引に対して拡張索引圧縮を有効化した場合に、どの程度まで圧縮されるのかをDBMS_COMPRESSIONパッケージを使用して見積もってください。
connect TRY/TRY12345
set linesize 200 pages 5000
set serveroutput on
DECLARE
i_OWNNAME varchar2(30) := 'TRY' ;
i_OBJNAME varchar2(30) := 'IDX_TAB42_COL3' ;
o_BLKCNT_CMP binary_integer ;
o_BLKCNT_UNCMP binary_integer ;
o_ROW_CMP binary_integer ;
o_ROW_UNCMP binary_integer ;
o_CMP_RATIO number ;
o_COMPTYPE_STR varchar2(128) ;
BEGIN
-- Execute
DBMS_COMPRESSION.GET_COMPRESSION_RATIO (
scratchtbsname => 'SCRATCHTBS',
ownname => i_OWNNAME,
objtype => 2, -- Table=1, Index=2
objname => i_OBJNAME,
subobjname => '',
comptype => DBMS_COMPRESSION.COMP_INDEX_ADVANCED_LOW,
blkcnt_cmp => o_BLKCNT_CMP,
blkcnt_uncmp => o_BLKCNT_UNCMP,
row_cmp => o_ROW_CMP,
row_uncmp => o_ROW_UNCMP,
cmp_ratio => o_CMP_RATIO,
comptype_str => o_COMPTYPE_STR,
subset_numrows => DBMS_COMPRESSION.COMP_RATIO_INDEX_MINROWS
);
-- Results
DBMS_OUTPUT.PUT_LINE ('| -------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE ('| THE RESULTS of DBMS_COMPRESSION.GET_COMPRESSION_RATIO ');
DBMS_OUTPUT.PUT_LINE ('| (Type : ' ||o_COMPTYPE_STR|| ')');
DBMS_OUTPUT.PUT_LINE ('| -------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE ('| Object : ' || ' : ' || i_OWNNAME || '.' || i_OBJNAME);
DBMS_OUTPUT.PUT_LINE ('| Compression Ratio = ' || o_CMP_RATIO );
DBMS_OUTPUT.PUT_LINE ('| NoComp Blocks = ' || o_BLKCNT_UNCMP );
DBMS_OUTPUT.PUT_LINE ('| Comp Blocks = ' || o_BLKCNT_CMP );
DBMS_OUTPUT.PUT_LINE ('| NoComp Rows = ' || o_ROW_UNCMP );
DBMS_OUTPUT.PUT_LINE ('| Comp Rows = ' || o_ROW_CMP );
DBMS_OUTPUT.PUT_LINE ('| -------------------------------------------------------');
END;
/
| -------------------------------------------------------
| THE RESULTS of DBMS_COMPRESSION.GET_COMPRESSION_RATIO
| (Type : "Compress Advanced Low")
| -------------------------------------------------------
| Object : : TRY.IDX_TAB42_COL3
| Compression Ratio = 9.9
| NoComp Blocks = 1587
| Comp Blocks = 160
| NoComp Rows = 63
| Comp Rows = 625
| -------------------------------------------------------
ちょいと懐かしさを感じる、DBMS_COMPRESSIONパッケージの登場です。懐かしいと言うのは、OLTP表圧縮が登場した当時、かなり多用していた自分がいたからだと思います。なので、同様に使用された経験のある方は、特に問題無く実行出来たのではないでしょうか?少しだけ解説しておきますね。
まず一番大切なのは、このDBMS_COMPRESSIONパッケージのGET_COMPRESSION_RATIOプロシージャの「objtype」オプションに「1」を指定した場合は表オブジェクト、「2」を指定した場合は索引オブジェクトに対して圧縮率を見積もることになります。
次に、このプロシージャを実行すると、内部的にサンプリングされた非圧縮のオブジェクトと圧縮されたオブジェクトの2つが生成(実行中に、USER_SEGMENTSビューを参照していると何となく推測できます)して、それらのオブジェクトのサイズを比較して圧縮率を計算しているようですから、かなり正確な結果が出力される思います。そのサンプリング量に関しては、「subset_numrows」オプションで指定することが出来ますが、引数に指定するその他のオプションに応じて、この「subset_numrows」オプションのデフォルト値が変化する点には十分ご注意ください。(「Oracle Database PL/SQLパッケージおよびタイプ・リファレンス 12cリリース1 (12.1)」で確認できます) ちなみに、今回の演習では、DBMS_COMPRESSIONパッケージで用意されている「DBMS_COMPRESSION.COMP_RATIO_INDEX_MINROWS」を使用してみましたが、何も指定しない時よりもサンプリング数が少なくなるようで、結果が出力されるまでの時間が短くなりましたので、ご興味のある方は、色々試してみてください。
そして、この「subset_numrows」オプションとペアで覚えておくべきオプションが「scratchtbsname」です。こちらは先ほど説明させて頂いた一時的なオブジェクトが作成される表領域を指定することが出来ます。上記の回答例では、表領域「SCRATCHTBS」を指定しています。
さて、今回の私の索引で試した結果としは「9.9倍」まで圧縮できるらしいですね。検証環境である為に同じような文字列が格納され過ぎていて、正直かなり高過ぎる結果です。本番環境でも同じ結果になるとは思わないでくださいね。
5. 演習4において、拡張索引圧縮の効果が見込まれる結果が出ましたので、実際に拡張索引圧縮を有効化してみましょう。
$ sqlplus /nolog
SQL> connect TRY/TRY12345
alter index IDX_TAB42_COL3 rebuild online compress advanced low ;
set linesize 150 pages 5000
col INDEX_NAME for a20
select INDEX_NAME, INDEX_TYPE, COMPRESSION, LEAF_BLOCKS
from USER_INDEXES order by 1 desc ;
INDEX_NAME INDEX_TYPE COMPRESSION LEAF_BLOCKS
-------------------- --------------------------- ------------- -----------
PK_TAB42_COL2_1 NORMAL ADVANCED LOW 2094
IDX_TAB42_COL3 NORMAL ADVANCED LOW 1558
はい、alter index文で索引再構成(INDEX REBUILD)を実行する際に、「compress advanced low」オプションを追記するだけで、拡張索引圧縮を有効化することが出来ます。演習4の長いPL/SQL文を見た後なので、よりシンプルに見えてきますね。カンターン!!
そして注目は索引のリーフブロック数ですね。演習3で確認した非圧縮時は「15,625」個でしたが、拡張索引圧縮を有効化することで「1,558」個まで縮小しています。まさらに、演習4で実行したDBMS_COMPRESSION.GET_COMPRESSION_RATIOで見積もった圧縮率とほぼ等しいですよね!!
6. 表TAB42の列COL4と列COL5に対しても非圧縮なB*Tree索引をそれぞれ作成し、その索引のリーフブロック数を確認して下さい。
$ sqlplus /nolog SQL> connect TRY/TRY12345 create index IDX_TAB42_COL4 on TAB42(COL4) ; create index IDX_TAB42_COL5 on TAB42(COL5) ; set linesize 150 pages 5000 col INDEX_NAME for a20 select INDEX_NAME, INDEX_TYPE, COMPRESSION, LEAF_BLOCKS from USER_INDEXES where INDEX_NAME like 'IDX_%' ; INDEX_NAME INDEX_TYPE COMPRESSION LEAF_BLOCKS -------------------- --------------------------- ------------- ----------- IDX_TAB42_COL3 NORMAL ADVANCED LOW 1558 IDX_TAB42_COL4 NORMAL DISABLED 15625 IDX_TAB42_COL5 NORMAL DISABLED 15625
こちらは、特に解説不要ですね。以降の演習の為の準備だと思って下さい。
追加作成した索引のリーフブロック数は、索引IDX_TAB42_COL3の非圧縮時と同じですよね。これは列データ長が同じ(100バイト)なので、当たり前と言えば当たり前ですね。
7. 表TAB42に対して、従来型のINSERT(ダイレクトではない)で1,000,000レコードをINSERTし、各索引の増加量を評価して下さい。
$ sqlplus /nolog
SQL> connect TRY/TRY12345
-- 1,000,000 rows inserted
insert into TAB42 select LEVEL + 1000000
, to_date('2015/09/25', 'YYYY/MM/DD') + mod(LEVEL, 12*5)
, rpad('sibacho', 100, '*')
, rpad('sibacho'||to_char(mod(LEVEL, 1000)), 100, '*')
, rpad('sibacho'||to_char(mod(LEVEL,10000)), 100, '*')
from DUAL connect by LEVEL <= 1000000 ;
commit ;
set linesize 150 pages 5000
col INDEX_NAME for a20
select INDEX_NAME, INDEX_TYPE, COMPRESSION, LEAF_BLOCKS
from USER_INDEXES
where INDEX_NAME like 'IDX_%' ;
INDEX_NAME INDEX_TYPE COMPRESSION LEAF_BLOCKS
-------------------- --------------------------- ------------- -----------
IDX_TAB42_COL3 NORMAL ADVANCED LOW 1558
IDX_TAB42_COL4 NORMAL DISABLED 15625
IDX_TAB42_COL5 NORMAL DISABLED 15625
-- オプティマイザ統計情報を再取得
exec DBMS_STATS.GATHER_TABLE_STATS(ownname => 'TRY', tabname => 'TAB42') ;
set linesize 150 pages 5000
col INDEX_NAME for a20
select INDEX_NAME, INDEX_TYPE, COMPRESSION, LEAF_BLOCKS
from USER_INDEXES
where INDEX_NAME like 'IDX_%' ;
INDEX_NAME INDEX_TYPE COMPRESSION LEAF_BLOCKS
-------------------- --------------------------- ------------- -----------
IDX_TAB42_COL3 NORMAL ADVANCED LOW 3367
IDX_TAB42_COL4 NORMAL DISABLED 41830
IDX_TAB42_COL5 NORMAL DISABLED 44499
拡張索引圧縮が有効な索引は従来型のINSERTでレコードを挿入した際にも圧縮されるのか?という疑問はお持ちじゃないでしょうか?私が探した限り、マニュアルには特にINSERTの仕方にはどこにも言及がなかったようなので、念のため、この演習では従来型INSERTを試した結果が上記の通りです。順番に解説していきますね。
まずは、既存で100万レコードが格納されている表TAB42に対して、さらに100万レコードを従来型INSERTで挿入しています。このINSERT+SELECT文は、演習1で実行したものからAPPENDヒント句を取り除いて、COL1がユニークになるように少し調整したものです。COL2,3,4,5へ格納される列データの量やカーディナリティは演習1と全く同じだと思って下さい。
でもって、挿入後、USER_INDEXESビューで各索引のリーフブロック数を確認してみましたが・・・あら?挿入前のリーフブロック数と変わっていない(演習6の結果と同じ)じゃないですか!!と言うように、焦らないで下さいね。
LEAF_BLOCKS列の値はオプティマイザ統計情報の一部ですから、オプティマイザ統計情報を収集し直さなくては最新の情報は確認出来ません。なので、今回は、表TAB42のオプティマイザ統計情報をDBNS_STATSパッケージで明示的に収集することで、表TAB42に作成されている全索引オブジェクトに関するオプティマイザ統計情報も収集しているわけです。
そして、結果としては拡張索引圧縮が有効な索引IDX_TAB42_COL3の増加量が、無効な索引の増加量よりも圧倒的に小さく抑えられている事が確認できていますから、拡張索引圧縮が有効な索引は従来型のINSERTでレコードを挿入した際にも圧縮されることが証明出来たと言う事になりますね。
ちなみに、演習6ではオプティマイザ統計情報を収集していませんでしたが各索引のリーフブロック数が確認出来たのは何故?と言うのは、Oracle Database 10gからは索引作成、又は再構成時にオプティマイザ統計情報が自動的に収集されるからですね。ちなみに、このようなオプティマイザ統計情報が索引作成処理の一部として自動的に収集される方法が、Oracle Database 12cではCreate Table AS Select(CTAS)処理やInsert As Select(IAS)処理等のダイレクト・パス処理にも適用されるようになっています。(表のオプティマイザ統計情報が対象)
[参考] Oracleホワイト・ペーパー Oracle Database 12cのオプティマイザ
8. 表TAB42に作成されている全ての索引に対して、一括で拡張索引圧縮を有効化した場合の圧縮率を見積もって下さい。
$ sqlplus /nolog
SQL> connect TRY/TRY12345
set linesize 200 pages 5000
set serveroutput on
DECLARE
o_INDEX_CR DBMS_COMPRESSION.COMPRECLIST ;
o_COMPTYPE_STR varchar2(128) ;
BEGIN
-- Execute
DBMS_COMPRESSION.GET_COMPRESSION_RATIO (
scratchtbsname => 'SCRATCHTBS',
ownname => 'TRY',
tabname => 'TAB42',
comptype => DBMS_COMPRESSION.COMP_INDEX_ADVANCED_LOW,
index_cr => o_INDEX_CR,
comptype_str => o_COMPTYPE_STR
);
-- Results
DBMS_OUTPUT.PUT_LINE ('| -------------------------------------------------------');
DBMS_OUTPUT.PUT_LINE ('| THE RESULTS of DBMS_COMPRESSION.GET_COMPRESSION_RATIO ');
DBMS_OUTPUT.PUT_LINE ('| (Type : ' ||o_COMPTYPE_STR|| ')');
DBMS_OUTPUT.PUT_LINE ('| -------------------------------------------------------');
for i in o_INDEX_CR.first .. o_INDEX_CR.last loop
DBMS_OUTPUT.PUT_LINE ('| INDEX# ' || i || ' : ' || o_INDEX_CR(i).OWNNAME || '.' ||
o_INDEX_CR(i).OBJNAME);
DBMS_OUTPUT.PUT_LINE ('| Compression Ratio = ' || o_INDEX_CR(i).CMP_RATIO );
DBMS_OUTPUT.PUT_LINE ('| NoComp Blocks = ' || o_INDEX_CR(i).BLKCNT_UNCMP );
DBMS_OUTPUT.PUT_LINE ('| Comp Blocks = ' || o_INDEX_CR(i).BLKCNT_CMP );
DBMS_OUTPUT.PUT_LINE ('| NoComp Rows = ' || o_INDEX_CR(i).ROW_UNCMP );
DBMS_OUTPUT.PUT_LINE ('| Comp Rows = ' || o_INDEX_CR(i).ROW_CMP );
DBMS_OUTPUT.PUT_LINE ('| -------------------------------------------------------');
end loop ;
END;
/
| -------------------------------------------------------
| THE RESULTS of DBMS_COMPRESSION.GET_COMPRESSION_RATIO
| (Type : "Compress Advanced Low")
| -------------------------------------------------------
| INDEX# 1 : TRY.PK_TAB42_COL2_1
| Compression Ratio = 1.4
| NoComp Blocks = 336
| Comp Blocks = 225
| NoComp Rows = 298
| Comp Rows = 444
| -------------------------------------------------------
| INDEX# 2 : TRY.IDX_TAB42_COL3
| Compression Ratio = 9.9
| NoComp Blocks = 1587
| Comp Blocks = 160
| NoComp Rows = 63
| Comp Rows = 625
| -------------------------------------------------------
| INDEX# 3 : TRY.IDX_TAB42_COL4
| Compression Ratio = 9
| NoComp Blocks = 1586
| Comp Blocks = 175
| NoComp Rows = 63
| Comp Rows = 571
| -------------------------------------------------------
| INDEX# 4 : TRY.IDX_TAB42_COL5
| Compression Ratio = 5.2
| NoComp Blocks = 1586
| Comp Blocks = 305
| NoComp Rows = 63
| Comp Rows = 328
| -------------------------------------------------------
はい、では最後に、DBMS_COMPRESSION.GET_COMPRESSION_RATIOプロシージャに追加された使い方(従来とはオプションの指定方法が異なる)を体験しておいて頂きましょう。演習4でも索引の圧縮率の見積もり方法を解説しましたが、あくまで一つの索引に限定した方法でしたね。上記の回答例では、任意の表に作成されている全索引に対して一括で圧縮率を見積もることが可能となっていますので、横着な私にとっては非常に便利に感じるわけです。
さて、Oracle Database 12cの新機能「拡張索引圧縮(Advanced Index Compression)」は如何でしたでしょうか?当初予定していた、従来から存在していた「接頭辞圧縮(プリフィックス圧縮 / キー圧縮)」についての解説まで手が回りきらなかったのが本当に申し訳ございませんでした。接頭辞圧縮にはあまり適していなかった索引も、今回の拡張索引圧縮では効果があると言うマニュアルにも記載のある部分をお見せしたかったのですが・・・。お時間のある方は、是非とも試して頂ければ幸いです。
繰り返しになりますが、本連載で扱う表やレコード(カーディナリティ)は検証目的で作成したものですから、演習の解説内に記載されている圧縮率についてはお客様の本番環境でも同じ結果となることを保証している訳ではなく、あくまで参考情報としてお取り扱い下さい。とは言え、その圧縮の効果には期待したい所はありますね。圧縮されれば索引セグメントのサイズが小さくなりますが、本当に素敵な恩恵はディスクサイズの節約でしょうか?私は違うと思います。私が思うに、バッファ・キャッシュ上へのキャッシュ効率の向上だと思います。非圧縮で100GBの索引が存在していたとしましょう。これを全てバッファ・キャッシュ上へキャッシュするには100GBのメモリが必要でしたが、拡張索引圧縮を有効化することで30GBまで索引セグメントのサイズが小さくなれば、30GBのメモリで全てキャッシュされることを意味しますから、バッファ・キャッシュ・ヒット率の向上に効果が期待できそうですよね。是非、この辺りのパフォーマンス検証は、皆さんのテスト環境でも試して頂ければと思います。
と言う事、今回も最後まで体験して頂きましてありがとうございました。是非、感想や質問をお待ちしておりますね。次回以降もどうぞよろしくお願い致します。その前に、JPOUG> SET EVENTS 20151017 でお会いしましょう!
(ご質問の方法はこちらにあります)
https://blogs.oracle.com/otnjp/shibacho-index
