Oracle12c 新機能

update:

第3回「Oracle12c (12.1.0.2) In-Memory Option」

著者:吉田 宗弘

1. Introduction

1.1 はじめに

企業が活動を行っていく上で最も価値の高いデータは、RDBMS に格納されています。RDBMS はデータを全て表形式で管理するため、基幹系システム等OLTP 系の処理には非常に適したデータ管理ツールであると言えます。対して基幹系のシステムから時々刻々と上がってくるデータを蓄積・分析するDWH 系のシステムは、RDBMS の得意とする所ではありません。そのため、基幹系システムへの影響を最小限に抑えDWH を構築する場合、基幹系のデータを別のDatabase に取込んでNoSQL, Hadoop, カラム型Database と言った非RDBMS 製品を使って分析を行っている企業もあるでしょう。
このようにして構築したDWH システムの最大の問題点は、基幹系システムからのデータの抽出とDWH システムへのデータのロードに大量の時間を要するため、最新のデータでの分析が行えない事にあります。この問題を解決するためOracle 社は、2008年にDWH 向けのAppliance 製品としてExadata を発表しました。これにり、基幹系システムで発生したデータをそのまま非常に効率的に分析を行う事が可能となりました。Exadata はOLTP系の処理もDWH系の処理も非常に効率帝に処理する事が可能なAppliance 製品ですが、専用のハードウェアを必要とするため非常に高価なシステムとなってしまいます。
2014年7月にリリースされたOracle 12c Release 1に対する最終のPSR (12.1.0.2) には、不具合修正や既存機能の強化だけでなく、DWH 系の処理性能を大幅に向上させる機能 (In-Memory Option) が追加されています。Option 機能のため、使用するには別途ライセンスの購入が必要となりますが、専用のハードウェアを必要としないため導入は非常に容易です。
今回は、Oracle 12.1.0.2 の目玉機能であるIn-Memory Option 機能について確認していきます。尚本書内でも簡単な性能検証を行っていますが、性能試験に使用した環境がVMware 上にセットアップした仮想環境のため、本書に記載されている性能値については、あくまで参考値としてご理解願います。

本機能については注目度も高く、Web 上で様々な技術情報や検証結果が公開されていますので、重複する内容については最小限の記載に留めています。本書を作成するにあたって参考にした資料のURL を巻末に記載していますので、本書と併せて確認される事をお勧めします。

1.2 In-Memory Option の特徴

In-Memory Option には、以下の特徴があります。
・Oracle 12.1.0.2 の新機能で、使用するためにはOracle Database In-Memory Option
のライセンスが必要となります。
・INMEMORY_SIZE 初期化パラメータで指定したサイズでSGA に、In-Memory
Column Store (以下 IMC) と呼ばれるMemory Pool が作成されます。INMEMORY_SIZE の最小サイズは100MBです。


SGA


・IMC は列指向のBuffer Cache として動作し、従来のBuffer Cache とIMCとの間で一貫性が保障されます。


SGA


・IMC は静的な領域として管理されるため、AMM (Automatic Memory Management)
による動的管理の対象外となります。
※ MEMORY_TARGET, SGA_TARGET, SGA_MAX_SIZE を指定している環境で
In-Memory Option を使用する場合は、INMEMORY_SIZE 分値を増加させる必要が
あります。
・IMCと従来のBuffer Cache のどちらを使用するかは、Optimizer が自動的に判断
します。
・Alter system flush … に相当するコマンドはありません。
  IMC を使用しているテーブルに対して、「Alter table ~ NO INMEMORY」を行う
 事で、個別にIMCからデータを削除する事が可能です。


・DBA が指定したTable, Partition, Materialized View が列フォーマットに変換され、
IMC 内のIn-Memory Compression Unit (以下 IMCU)に移入されます。
任意の列を選択して、IMCU に移入する事も可能。
※ IMC は、列データを格納するための1MB のPool とメタデータやジャーナル
を格納するための64KBのPool から構成されます。
IMCU に移入されているデータが更新されると、ジャーナルに更新内容が記録され、IMCU を使用した読取り一貫性とIMCU への再移入に利用されます。
・IMCU にデータを移入する際の圧縮レベルや優先レベルを指定可能

※ 優先レベルは、列データの移入順序を制御するだけで性能に影響を与えるものではありません。In-Memory Option がサポートしている圧縮レベル, 優先順位は以下の通りです。

圧縮レベル

圧縮レベル

圧縮率

概要

NO MEMCOMPRESS

無圧縮

データを圧縮しないで移入

FOR DML

低圧縮

高圧縮

DMLのパフォーマンスを最適化して移入 (最低限の圧縮)

FOR QUERY LOW

問合せのパフォーマンスを最適化して移入 (DEFAULT)

FOR QUERY HIGH

問合せのパフォーマンスと領域節約を最適化して移入

FOR CAPACITY LOW

領域節約に比重をおいてバランスを調整して移入

FOR CAPACITY HIGH

領域節約を最適化して移入


優先レベル

優先レベル

優先度

概要

CRITICAL

オブジェクトはDB のオープン直後に移入が開始される。

HIGH

CRITICAL オブジェクトの移入後にIMC に空き領域があれば移入される。

MEDIUM

HIGH オブジェクトの移入後にIMC に空き領域があれば移入される。

LOW

MEDIUM オブジェクトの移入後にIMC に空き領域があれば移入される。

NONE

オブジェクトの初回スキャン時にIMC に空き領域があれば移入される。 (DEFAULT)


・IMCU 毎に各列の最大値/最小値を保持する事で、参照するメモリ量を大幅に削減
しています。 (Column Store Storage Index)


Column Store Storage Index


・In-Memory 化対象のテーブルが更新されると、コミット時にIMCU 内の該当行が
無効化され、定期的に又はQuery 発行時に再移入される。DML の実行とIMCU の
更新を非同期にする事で、In-Memory 化されたテーブルに対する更新性能の低下を

最小限にしている。

・再移入は、以下のタイミングで自動的に実施される。
 ・多数の行が更新された場合 (再移入)
 ・2分間隔 (トリクル再移入)
・以下のObjectは、In-Memory Option の対象外となります。
 ・SYSユーザが所有者でSYSTEM又はSYSAUX表領域に格納されているObject
  ・索引構成表
  ・クラスタ表
  ・LONG データ型
  ・行外LOB
  ・4KB を超えるVarchar2, RAW (MAX_STRRING_SIZE 初期化パラメータを
EXTENDEDに明示的に設定している事が前提)
  ・64KB 未満のObject
  ・Advanced Replication の設定が行われているObject
・RAC 環境の場合、IMCU を複数Node への分散配置が可能となります。
・Exadata又はSuperCluster環境では、IMCUを複数Nodeへ冗長配置が可能です。
  ※ IMCU の冗長配置を行うと、Node が停止/復旧した際に大量のデータが系間
   パスを通じて転送されるため、IMCU の冗長配置は系間パスにInfiniBand を 使用しているExadata 又は SuperCluster 環境のみ使用可能となります。

2. In-Memory Option の仕様

前節ではOracle 12.1.0.2 の新機能である、In-Memory Option の概要について説明を行いました。本節ではIn-Memory Option の仕様について実際に動作させながら確認を行います。

2.1 関連する初期化パラメータ

先ず、デフォルト状態のパラメータを見てみましょう。

SQL> show parameters inmemory

NAME                                            TYPE        VALUE
----------------------------------------------- ----------- -----------
inmemory_clause_default                         string
inmemory_force                                  string      DEFAULT
inmemory_max_populate_servers                   integer     0
inmemory_query                                  string      ENABLE
inmemory_size                                   big integer 0
inmemory_trickle_repopulate_servers_percent     integer     1
optimizer_inmemory_aware                        boolean     TRUE

それでは、上記のパラメータについて説明を行います。 (括弧内はDEFAULT 値)


INMEMORY_CLAUSE_DEFAULT:(NULL)
本パラメータには、Table, Materialize View を新規に作成する際のINMEMORY 句のDEFAULT 設定を指定します。本パラメータを ‘NO INMEMORY’ 又はNULL 以外に設定すると、明示的にNO INMEMORY を指定せずに新規作成したTable, Materialized View は全ての列がIMC に移入される設定となります。
通常は本パラメータを設定せずに、IMC に移入する列を明示的に指定してTable, Materialized View を作成するのが良いでしょう。


[注意]
Oracle のマニュアル (Database Reference) で本パラメータを’INMEMORY …’ と設定した時に、「NO INMEMORY として指定されたものを含めて」IMC に移入されるとありますが、これは誤りです。本パラメータはDEFAULT を設定するものですので、NO INMEMORY を指定して作成されたTable, Materialized View はIMC 移入の対象外となります。


INMEMORY_FORCE:(DEFAULT)
本パラメータはINMEMORY 指定されたTable, Materialized View をIMC に移入するか否かを指定します。DEFAULT ではINMEMORY 指定されたTable, Materialized View はIMC に移入されますが、OFF とするとIMC に移入されなくなります。本パラメータは、テスト等の目的でINMEMORY 機能を無効化する場合にのみ設定を変更します。


INMEMORY_MAX_POPULATE_SERVERS (CPUコア数÷2, pga_aggregate_target÷ 512MB の少ない方)

本パラメータでは、In-Memory 対象Object をIMCUにローデエィグを行うバックグラウンド・プロセス数の最大数を指定します。


INMEMORY_QUERY:(INMEMORY_SIZE が指定されている場合はENABLE)
本パラメータを使用すると、INMEMORY 問合せを有効化/無効化する事ができます。INMEMORY Option が有効化された環境で、INMEMORY 問合せを使用しない性能測定を行うような場合、本パラメータをDISABLE に設定する事で一時的にINMEMORY 問合せを無効化できます。


INMEMORY_SIZE:(0)

本パラメータでは、IMC に割当てるメモリサイズを指定します。INMEMORY Option を使用する場合、本パラメータは100MB 以上に設定する必要があります。IMC はメタデータやジャーナルを格納するための64KB Pool と列データを格納するための1MB Pool から構成されます。64KB Pool, 1MB Pool の配分は、本パラメータの指定によって自動的に決定されます。本パラメータで設定する領域は静的領域となるため、変更後はインスタンスの再起動が必要となります。(PDB 環境に本パラメータを指定する場合は、CDB に割当てられているIMC に対してPDB 毎の上限値を設定するだけのためインスタンスの再起動は不要です。)


INMEMORY_TRICKLE_REPOPUATE_SERVER_PERCENT:(1)

本パラメータでは、ワーカー・プロセスがトリクル再移入を実行する最大時間の割合を指定します。本パラメータを0に指定すると、トリクル再移入は行われなくなります。本パラメータは50が最大値となります。


OPTIMIZER_INMEMORY_AWARE:(TRUE)

本パラメータでは、In-Memory 機能に対するオプティマイザ・コスト・モデル拡張機能を有効化/無効化します。


2.2 関連するデータ・ディクショナリ

それでは次に、In-Memory Option に関するデータ・ディクショナリを見てみましょう。
In-Memory Option に関する主なデータ・ディクショナリとして、以下のものがあります。下記以外にもIn-Memory Option に関するディクショナリはありますが、現在ドキュメント化されているのは以下の3つのみです。

ディクショナリ名

概要

V$IM_COLUMN_LEVEL

In-Memory 化されたカラム毎の圧縮レベルに関する情報の一覧

V$IM_SEGMENTS

DB内の全In-Memory セグメント情報の一覧

V$IM_USER_SEGMENTS

現行ユーザのIn-Memory セグメント情報の一覧

※ 上記以外にも、DBA_TABLES, DBA_SEGMENTS, DBA_TABPARTITIONS 等
にIn-Memory Option に関する列 (INMEMORY_PRIORITY 等) が追加されて
います。

2.3 関連するパッケージ

次に、In-Memory Option に関連するパッケージを見てみましょう。In-Memory Option に関連するパッケージとして、以下のものがあります。

パッケージ名

概要

DBMS_COMPRESSTION

圧縮率の見積りで、In-Memory Option の圧縮タイプに対応
但し、列を選択しての見積りには対応していない。
実際にデータをスキャンして圧縮率の見積りを行うだけだが、使用する場合にはINMEMORY_SIZE を指定しておく必要がある。

DBMS_INMEMORY

手動で移入/再移入の開始


DBMS_INMEMORY Package を使用すると、手動で移入/再移入を開始する事ができます。但し、トリクル再移入は2分間隔で実行されますし、In-Memory Option の設定を行ったテーブルにアクセスする事で移入も開始される事から、使用頻度は低いと思われます。

DBMS_COMPRESSION Package は、元々Advanced Compression やExadata のHybrid Columnar Compression を使用した際の圧縮率の見積りを行うPackage でしたが、本Package がIn-Memory Option の圧縮にも対応しました。
comptype パラメータにCOMP_INMEMORY_QUERY_HIGH 等、In-Memory Option のパラメータを指定する事で圧縮率の見積りを行う事ができます。 本Package を使用する際には、事前にINMEMORY_SIZE 初期化パラメータを設定してインスタンスを再起動しておく必要があります。それでは実際に確認してみましょう。

-- INMEMORY_SIZE を1024M に設定して、インスタンスを再起動
-- 確認で使用するTable の作成&データセット&事前準備
SQL> Create table Sales (
id         number(12),
StoreID    number(4),
ItemID     number(8),
SalesCnt   number(6),
txt        varchar2(256),
SalesDate  date,
constraint pk_sales primary key (id)
);

SQL> create index ix1_sales on sales(storeID);

SQL> declare
ix   pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(256) := dbms_random.string('p', 256);
begin
select nvl(max(id),0) into ix from sales;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..1000 loop
insert into Sales select level + ix,
trunc(dbms_random.value(1,100)),
trunc(dbms_random.value(1000, 5000)),
trunc(dbms_random.value(1, 10)),
vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/

SQL> select count(*) from SCOTT.SALES;
COUNT(*)
----------
100000000

SQL> alter index pk_sales rebuild tablespace users;
SQL> alter index ix1_sales rebuild tablespace users;
SQL> exec dbms_stats.gather_schema_stats(ownname=>'SCOTT');
SQL> alter system flush shared_pool;
SQL> alter system flush buffer_cache;
SQL> commit;

SQL> select segment_type, segment_name, bytes/1048576 as mbyte from user_segments;
SEGMENT_TY SEGMENT_NA    MBYTE
---------- ---------- --------
TABLE      SALES       31285.0
INDEX      PK_SALES     1747.0

INDEX      IX1_SALES    1534.0

-- 圧縮率の見積り
SQL> set serveroutput on
SQL> declare
v_blk_cmp    pls_integer;
v_blk_uncmp  pls_integer;
v_row_cmp    pls_integer;
v_row_uncmp  pls_integer;
v_ratio      number;
v_comptype   varchar2(100);
begin
dbms_compression.get_compression_ratio (
scratchtbsname => 'USERS',
ownname        => 'SCOTT',
objname        => 'SALES',
subobjname     => NULL,
comptype       => dbms_compression.comp_inmemory_query_high,
blkcnt_cmp     => v_blk_cmp,
blkcnt_uncmp   => v_blk_uncmp,
row_cmp        => v_row_cmp,
row_uncmp      => v_row_uncmp,
cmp_ratio      => v_ratio,
comptype_str   => v_comptype);
dbms_output.put_line('blk_cmp ' || v_blk_cmp || '  blk_uncmp ' || v_blk_uncmp);
dbms_output.put_line('row_cmp ' || v_row_cmp || '  row_uncmp ' || v_row_uncmp);
dbms_output.put_line('ratio   ' || v_ratio);
dbms_output.put_line('comptyp ' || v_comptype);
end;
/

blk_cmp 0  blk_uncmp 40001
row_cmp 0  row_uncmp 24
ratio   21.8
comptyp "In-memory Memcompress Query High"

約31GB のテーブルに対して21.8% となるため、約6.8GB のメモリが必要となります。
しかし、列を選択してIn-Memory 化する事で使用するメモリ量を削減する事が可能です。

-- INMEMORY_SIZE の設定を行っていない環境で上記操作を行うと、以下のエラーとなります。
ORA-20000: Compression advisor Unable to load table inmemory
ORA-06512: "SYS.PRVT_COMPRESSION", 行1269
ORA-06512: "SYS.PRVT_COMPRESSION", 行237
ORA-06512: "SYS.DBMS_COMPRESSION", 行218
ORA-06512: 行9

2.4 関連するバックグラウンド・プロセス

下図に示す通り、IMCO (In-Memory Coordinator) プロセスがコーディネータとして機能し、実際の移入 (ポピュレーション) はワーカー・プロセス (Wnnn) が実行します。




3. In-Memory Option の詳細

3.1 In-Memory Option を使用した性能

それでは実際に、In-Memory Option を使用する事でどの程度性能が向上するか確認してみましょう。

-- テーブルをIn-Memory 化していない状態でSQL を実行してみます。
SQL> set timing on
SQL> set autotrace on exp
SQL> select min(salesdate), max(salesdate), count(*) from sales where storeid=10;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-08-04 14-11-11    1008582
経過: 00:18:19.78

実行計画

Plan hash value: 2413220726

--------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |           |     1 |    11 |   900K  (1)| 00:00:36 |
|   1 |  SORT AGGREGATE                      |           |     1 |    11 |            |          |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| SALES     |  1008K|    10M|   900K  (1)| 00:00:36 |
|*  3 |    INDEX RANGE SCAN                  | IX1_SALES |  1012K|       |  2005   (2)| 00:00:01 |
--------------------------------------------------------------------------------------------------

-- 次に上のSQL で使用できる項目をIn-Memory 化してみます。
SQL> alter table sales inmemory;
SQL> alter table sales inmemory priority high
inmemory memcompress for capacity high (storeid)
no inmemory (salescnt, txt);

-- テーブルのデータをIMCU に移入中の状態
SQL> select *  from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS     CON_ID
---------- ------ --------------- ------------- ----------------- ----------
SALES                 TABLE      USERS          721551360   32804700160         21400625152
STARTED    HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW              0

-- IMCU への移入が完了した状態
SQL> select *  from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS     CON_ID
---------- ------ --------------- ------------- ----------------- ----------
SALES                 TABLE      USERS          828440576   32804700160         19754033152

COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW              0

-- 移入状況は、populate_status 列で確認可能です。
-- 列を選択してIMCU に移入を行ったため、v$im_user_segments では圧縮指定
-- (inmemory_compress) が QUERY LOW と表示されていますが、列毎の正しい圧縮指定は
-- v$im_column_level で確認可能です。
SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      ID         DEFAULT
SCOTT      SALES      STOREID    FOR CAPACITY HIGH
SCOTT      SALES      ITEMID     DEFAULT
SCOTT      SALES      SALESCNT   NO INMEMORY
SCOTT      SALES      TXT        NO INMEMORY
SCOTT      SALES      SALESDATE  DEFAULT

-- 先の例 (Inmemory_size = 1024M) ではIMC のサイズが小さ過ぎるため、全てのデータをIMCU に
-- 移入する事ができませんでした。
-- そのような場合、移入は完了 (populate_status = COMPLETED) しますが、未移入データサイズ
-- (bytes_not_populated) が 0 となっていません。
-- alert log には、以下のようにIMC 容量不足の警告メッセージが記録されています。
Fri Jan 16 16:41:21 2015
Insufficient memory to populate table to inmemory area

-- ではこの状態で、先程と同じSQL を実行してみます。
SQL> select min(salesdate), max(salesdate), count(*) from sales where storeid=10;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-08-04 14-11-11    1008582
経過: 00:09:35.63

実行計画

Plan hash value: 1047182207

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |     1 |    11 | 46513  (14)| 00:00:02 |
|   1 |  SORT AGGREGATE             |       |     1 |    11 |            |          |
|*  2 |   TABLE ACCESS INMEMORY FULL| SALES |  1008K|    10M| 46513  (14)| 00:00:02 |
-------------------------------------------------------------------------------------

-- 実行計画がINDEX RANGE SCAN からTABLE ACCESS INMEMORY FULL に変更され、性能が約2倍に
-- なりました。現在はIMC の容量が小さいため全てのデータが移入できていません。
-- IMC の容量を増やして、全データを移入してみます。
-- inmemory_size を3840M に設定してインスタンス再起動
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS         2052128768   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0



-- 全データがIMCU に移入できたので、索引を削除して、同じクエリーを実行してみます。
SQL> drop index ix1_sales;
SQL> select min(salesdate), max(salesdate), count(*) from sales where storeid=10;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-08-04 14-11-11    1008582
経過: 00:00:02.29
→ 約480倍高速化された。

-- 使用しているメモリ量の確認
SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896 2098200576 DONE                0
64KB POOL      788529152   21037056 DONE                0
→ 合計で約2GB の領域を使用

-- 必要最低限のデータのみIMCU に移入してみる。
SQL> alter table sales inmemory priority high
inmemory memcompress for capacity high (storeid, salesdate)
no inmemory (id, itemid, salescnt, txt);

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      ID         NO INMEMORY
SCOTT      SALES      STOREID    FOR CAPACITY HIGH
SCOTT      SALES      ITEMID     NO INMEMORY
SCOTT      SALES      SALESCNT   NO INMEMORY
SCOTT      SALES      TXT        NO INMEMORY
SCOTT      SALES      SALESDATE  FOR CAPACITY HIGH

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896  672137216 DONE                0
64KB POOL      788529152   21037056 DONE                0
→ 約700MB で済んだ
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS          691077120   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0

SQL> select min(salesdate), max(salesdate), count(*) from sales where storeid=10;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-08-04 14-11-11    1008582
経過: 00:00:03.64

→ 約300倍高速化された。

3.2 圧縮方法による使用メモリ量の差異 (列単位のIn-Memory 化)

前節ではIn-Memory Option を使用した際の性能について確認を行いましたので、本節では圧縮方法を変更する事による使用メモリ量の差異について見てみましょう。

-- 圧縮方式をCAPACITY HIGH からQUERY HIGH に変更
SQL> alter table sales inmemory priority high
inmemory memcompress for query high (storeid, salesdate)
no inmemory (id, itemid, salescnt, txt);
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS          691077120   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0
→ 容量変わらず

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896  672137216 DONE                0
64KB POOL      788529152   21037056 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level
where inmemory_compression != 'NO INMEMORY';
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      STOREID    FOR QUERY HIGH
SCOTT      SALES      SALESDATE  FOR QUERY HIGH

-- 圧縮方式をQUERY HIGH からQUERY LOWに変更
SQL> alter table sales inmemory priority high
inmemory memcompress for query low (storeid, salesdate);
SQL> select *  from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS          691077120   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0
→ 容量変わらず

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896  672137216 DONE                0
64KB POOL      788529152   21037056 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level
where inmemory_compression != 'NO INMEMORY';
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      STOREID    FOR QUERY LOW
SCOTT      SALES      SALESDATE  FOR QUERY LOW



-- 圧縮方式をQUERY LOW からCAPACITY LOWに変更
SQL> alter table sales inmemory priority high
inmemory memcompress for capacity low (storeid, salesdate);
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS          691077120   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0
→ 容量変わらず

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896  672137216 DONE                0
64KB POOL      788529152   21037056 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level
where inmemory_compression != 'NO INMEMORY';
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      STOREID    FOR CAPACITY LOW
SCOTT      SALES      SALESDATE  FOR CAPACITY LOW

-- 圧縮方式をCAPACITY LOW からDMLに変更
SQL> alter table sales inmemory priority high
inmemory memcompress for dml (storeid, salesdate);
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS         1355874304   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0
→ メモリ使用量が約2倍 (1.3GB) になった

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896 1336934400 DONE                0
64KB POOL      788529152   21037056 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level
where inmemory_compression != 'NO INMEMORY';
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      STOREID    FOR DML
SCOTT      SALES      SALESDATE  FOR DML

→ 列を指定してのIn-Memory 化では、圧縮方式がDML 以外のケースではメモリ使用量に差異は 見られなかった。

-- 圧縮方式をDML からNO MEMCOMPRESSに変更

SQL> alter table sales inmemory priority high
inmemory no memcompress (storeid, salesdate);
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES                 TABLE      USERS         1355874304   32804700160                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY LOW                       0
→ DML の時と同じ

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896 1336934400 DONE                0
64KB POOL      788529152   21037056 DONE                0

 

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level
where inmemory_compression != 'NO INMEMORY';
OWNER      TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT      SALES      STOREID    NO MEMCOMPRESS
SCOTT      SALES      SALESDATE  NO MEMCOMPRESS

→ 列を指定してのIn-Memory 化では、圧縮方式がDML/NO MEMCOMPRESS のケースとそれ以外のケースの2パターンのみ見られた。

 

[結果] 列指定でIn-Memory 化した際のメモリ使用量
      In-Memory 化するデータによって、異なる可能性があります。

圧縮形式

1MB Pool 使用量

64KB Pool 使用量

合計

FOR Capacity High

641MB

20 MB

661MB

FOR Capacity Low

641MB

661MB

FOR Query High

641MB

661MB

FOR Query Low

641MB

661MB

FOR DML

1275MB

1295MB

No Memcompress

1275MB

1295MB

 

3.3 圧縮方法による使用メモリ量の差異 (セグメント単位のIn-Memory 化)

前節では列を指定してIn-Memory 化した際に、圧縮方法により使用されるメモリ量の差異について確認を行いました。本節では、セグメント単位でIn-Memory 化した際の圧縮方法による使用メモリ量の差異について確認します。

-- 列指定の時よりも使用メモリ量が増加するため、セグメント単位にIn-Memory 化するテーブルを
-- 同じ構成で作成 (データ量は1/20)
SQL> Create table Sales2 (
id         number(12),
StoreID    number(4),
ItemID     number(8),
SalesCnt   number(6),
txt        varchar2(256),
SalesDate  date,
constraint pk_sales2 primary key (id)
);
-- txt 列もIn-Memory 化するため、txt 列の値の種類を増やしてデータ登録
SQL> declare
ix   pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(250) := dbms_random.string('p', 250);
begin
select nvl(max(id),0) into ix from sales2;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..50 loop
insert into Sales2 select level + ix,
trunc(dbms_random.value(1,100)),
trunc(dbms_random.value(1000, 5000)),
trunc(dbms_random.value(1, 10)),
to_char(level, 'FM999999') || vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/
SQL> select count(*) from sales2;
COUNT(*)
----------
5000000

SQL> select segment_type, segment_name, bytes/1048576 as mbyte from user_segments
where segment_name = 'SALES2';
SEGMENT_TY SEGMENT_NA    MBYTE
---------- ---------- --------
TABLE      SALES2       1568.0

-- 先に列指定でIn-Memory 化したIMCU を破棄
SQL> Alter table sales no inmemory;
SQL> select * from v$im_segments;

レコードが選択されませんでした。

-- 圧縮指定をCAPACITY HIGH で移入
SQL> alter table sales2 inmemory priority high
memcompress for capacity high;

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES2                TABLE      USERS           68222976    1644167168                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR CAPACITY HIGH                   0

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896   69206016 DONE                0
64KB POOL      788529152    1114112 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;
レコードが選択されませんでした。

-- 圧縮方式をCAPACITY HIGH からQUERY HIGH に変更
SQL> alter table sales2 inmemory priority high
memcompress for query high;

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES2                TABLE      USERS          632356864    1644167168                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR QUERY HIGH

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896  715128832 DONE                0
64KB POOL      788529152    1114112 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;

レコードが選択されませんでした。

-- 圧縮方式をCAPACITY LOWからDML に変更
SQL> alter table sales2 inmemory priority high
memcompress for dml;

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES2                TABLE      USERS         2225602560    1644167168                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  FOR DML                             0

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896 2591031296 DONE                0
64KB POOL      788529152    2621440 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;
レコードが選択されませんでした。

-- 圧縮方式をDMLからNO MEMCOMPRESS に変更
SQL> alter table sales2 inmemory priority high
no memcompress;

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION           CON_ID
---------- ------ --------------- ------------- -------------------------- ----------
SALES2                TABLE      USERS         2288517120    1644167168                   0
COMPLETED  HIGH   AUTO            NO DUPLICATE  NO MEMCOMPRESS                      0

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_S     CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL      3220176896 2658140160 DONE                0
64KB POOL      788529152    2621440 DONE                0

SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;
レコードが選択されませんでした。

→ セグメント単位のIn-Memory 化では、圧縮方式によって67MB ~ 2.5GB まで使用されるメモリ   
量が大きく変わっている。
v$im_user_segments.inmemory_compression は、列を指定してIn-Memory 化を行った場合は、
正しい値を取る事ができない。

セグメント単位のIn-Memory 化を行った場合、v$im_column_level には情報はリストされない。

[結果] セグメント指定でIn-Memory 化した際のメモリ使用量
      In-Memory 化するデータによって、異なる可能性があります。


圧縮形式

1MB Pool 使用量

64KB Pool 使用量

合計

FOR Capacity High

66MB

1 MB

67MB

FOR Capacity Low

208MB

209MB

FOR Query High

682MB

683MB

FOR Query Low

607MB

608MB

FOR DML

2471MB

2472MB

No Memcompress

2535MB

2536MB

 

3.4 In-Memory Option のPriority 設定

In-Memory Option では、IMC へのデータ移入順序をPriority で制御する事ができます。TableやPartitionに対してIn-Memory Option の設定を行われている状態でDBがオープンされると、CRITICAL → HIGH → MEDIUM → LOW の順にIMC へのデータ移入が行われます。 (Priority NONE は、該当テーブルへのアクセス時に移入が行われます。) IMC に十分な空き容量が無くなると、IMC への移入は中断されます。それでは、既にPriority の低いオブジェクトがIMC に移入されている状態で、IMC の空き容量を超えるPriority の高いオブジェクトが作成された場合、どのようになるか確認してみましょう。

-- 現在IMC を使用しているテーブルと同じ容量のテーブルを作成
SQL> Create table sales3 as select * from sales2 nologging;
SQL> select count(*) from sales3;
COUNT(*)
----------
5000000

-- 元テーブルと同じ圧縮属性 (NO MEMCOMPRESS) で優先レベル CRITICAL に設定
SQL> Alter table sales3 inmemory priority critical no memcompress;
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION       CON_ID
---------- -------- --------------- ------------- ---------------------- ----------
SALES2                TABLE      USERS         2288517120    1644167168                   0
COMPLETED  HIGH     AUTO            NO DUPLICATE  NO MEMCOMPRESS                  0

SALES3                TABLE      USERS          427491328    1644167168          1265729536
STARTED    CRITICAL AUTO            NO DUPLICATE  NO MEMCOMPRESS                  0
→ SALES3 の移入が開始された状態

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION       CON_ID
---------- -------- --------------- ------------- ---------------------- ----------
SALES2                TABLE      USERS         2288517120    1644167168                   0
COMPLETED  HIGH     AUTO            NO DUPLICATE  NO MEMCOMPRESS                  0

SALES3                TABLE      USERS          464191488    1644167168          1223786496
COMPLETED  CRITICAL AUTO            NO DUPLICATE  NO MEMCOMPRESS                  0
→ 未移入データが残っている状態で全ての移入が完了した状態

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_STATU     CON_ID
------------ ----------- ---------- -------------- ----------
1MB POOL      3220176896 3220176896 OUT OF MEMORY           0
64KB POOL      788529152    3342336 DONE                    0
→ 1MB のMemory Pool に空きが無い状態



-- IMC が不足すると、Alert log にも警告が記録されます。
$ tail $ORACLE_BASE/diag/…/trace/alert_ora121.log
:
Wed Mar 25 11:10:30 2015
Insufficient memory to populate table to inmemory area

-- この状態で優先レベルの高いテーブルにアクセスしてみます。
SQL> set autotrace on exp
SQL> select min(salesdate), max(salesdate), count(*) from sales3 where storeid=10;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-12-08 15-03-16      50521

                                : 途中省略
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     1 |    11 | 41413   (1)| 00:00:02 |
|   1 |  SORT AGGREGATE             |        |     1 |    11 |            |          |
|*  2 |   TABLE ACCESS INMEMORY FULL| SALES3 | 50505 |   542K| 41413   (1)| 00:00:02 |
--------------------------------------------------------------------------------------
: 途中省略
→ IMC にアクセスする実行計画となっています。

SQL> set autotrace off
SQL> select min(salesdate), max(salesdate), count(*) from sales3 where storeid=11;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-12-08 15-03-16      50215

SQL> select min(salesdate), max(salesdate), count(*) from sales3 where storeid=15;
MIN(SALE MAX(SALE   COUNT(*)
-------- -------- ----------
14-12-08 15-03-16      50368

-- テーブル毎のIMC の使用量を確認
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_STATU INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION       CON_ID
-------------- -------- --------------- ------------- ---------------------- ----------
SALES2                TABLE      USERS         2288517120    1644167168                   0
COMPLETED      HIGH     AUTO            NO DUPLICATE  NO MEMCOMPRESS                  0

SALES3                TABLE      USERS          464191488    1644167168          1223786496
COMPLETED      CRITICAL AUTO            NO DUPLICATE  NO MEMCOMPRESS                  0
→ クエリ実行前とテーブル毎のIMC の使用量は変わっておらず、Priority の低いテーブルのIMCU
がページアウトしてPriority の高いテーブルによって再利用される訳ではない。
In-Memory 化の際に指定するPriority は、単にIMC に移入する順序を制御するだけで、Priority
によって移入後の性能が変わる訳ではない。

SQL> alter table sales2 no inmemory;
SQL> alter table sales3 no inmemory;

 

3.5 Priority がNone に設定されているTable のIMCへの移入

前節までは、Priority がNone 以外のTable について確認を行ってきました。本節ではPriority がNone のTable について確認してみましょう。In-Memory Option のセミナー資料 (Oracle Database In-Memory:メモリー構造と設定) には、以下のように記載されています。

・SELECT 文によるクエリーが索引のみで結果が返される場合、ポピュレーションはトリガーされない。
- FULL ヒントを付ける事で明示的にポピュレーションを発生させられる。
・SELECT /*+ FULL (t1) */

・トランザクションの中でFull Scan される場合はトリガーされない。
- 例 : CREATE TABLE NO_IMMEM_TBL1 AS SELECT * FROM IMMEM_TB1
- 例 : INSERT … SELECT * FROM INMEM_TBL2

・スキャンの完了を待たずにポピュレーションは開始される

それでは実際に上記の記載通りになるか確認してみましょう。

-- In-Memory Option の設定が行われているTable を確認
SQL> select owner, table_name, inmemory, inmemory_priority
from dba_tables
where inmemory_priority is not null;
レコードが選択されませんでした。

-- テーブルと索引の対応を確認
SQL> select table_name, index_name, column_name, column_position as pos
from user_ind_columns
order by 1,2,4;
TABLE_NAME      INDEX_NAME      COLUMN_NAME         POS
--------------- --------------- ------------------ ----
SALES           IX1_SALES       STOREID               1
PK_SALES        ID                    1
SALES2          PK_SALES2       ID                    1

-- Priority None でIn-Memory Option の設定を実施&確認
SQL> alter table sales2 inmemory priority none;
SQL> select * from v$im_user_segments;

レコードが選択されませんでした。

-- 索引アクセス&実行計画確認&移入状況確認
SQL> set autotrace on exp
SQL> select max(id), min(id) from sales2;
MAX(ID)    MIN(ID)
---------- ----------
5000000          1

実行計画
----------------------------------------------------------
Plan hash value: 4055107189

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |     1 |     6 |  2924   (3)| 00:00:01 |
|   1 |  SORT AGGREGATE       |           |     1 |     6 |            |          |
|   2 |   INDEX FAST FULL SCAN| PK_SALES2 |  5000K|    28M|  2924   (3)| 00:00:01 |
-----------------------------------------------------------------------------------

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_STATU INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION       CON_ID
-------------- -------- --------------- ------------- ---------------------- ----------
SALES2                TABLE      USERS          431882240    1644167168           415801344
STARTED        NONE     AUTO            NO DUPLICATE  FOR QUERY LOW                   0
→ 移入が開始されている。

-- トランザクション内でのFull Scan を確認
SQL> set autotrace off
SQL> alter table sales2 no inmemory;
SQL> alter table sales2 inmemory priority none;
SQL> create table aaa as select * from sales2 where rownum <= 100;
SQL> insert into aaa select * from sales2 where rownum <= 100;
SQL> select * from v$im_user_segments;
レコードが選択されませんでした。
→ 移入は開始されていない。

-- 通常のOLTP系のクエリーを実行してみる。
SQL> select * from sales2 where id in (100, 1000, 99999);
: 省略
-- 移入状況の確認
SQL> select * from v$im_segments;
レコードが選択されませんでした。

→ 索引でクエリーが完結するかではなく、OLTP 系のクエリーの場合ポピュレーションがトリガー

   されないが、IMC を使用するようなクエリーの場合はポピュレーションがトリガーされる。

 

3.6 IMC への再移入/トリクル再移入

In-Memory 化されているTable が更新されると、ジャーナルに更新内容が記録されIMC への再移入は更新トランザクションとは非同期で行われます。再移入は、以下のタイミングで自動的に実施されます。

[再移入が実施されるタイミング]
・多数の行が更新された時 (再移入)
・2分間隔 (トリクル再移入)
  トリクル再移入は、初期化パラメータ  "inmemory_trickle_repopulate_servers_percent" を

  0 に設定すると行われなくなります。

それでは実際に、In-Memory 化されているTable にDML を発行してIMC に再移入されている状況を確認してみましょう。

-- SALES 表をIMCに再移入
SQL> alter table sales inmemory priority high
       inmemory memcompress for capacity low (storeid, itemid, salesdate, salescnt)
       no inmemory (id, txt);

SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_STATU INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION       CON_ID
-------------- -------- --------------- ------------- ---------------------- ----------
SALES                 TABLE      USERS          983629824   32804700160                   0
COMPLETED      HIGH     AUTO            NO DUPLICATE  FOR QUERY LOW                   0

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_STATU     CON_ID
------------ ----------- ---------- -------------- ----------
1MB POOL      3220176896  964689920 DONE                    0
64KB POOL      788529152   21037056 DONE                    0

SQL> select owner, table_name, column_name, inmemory_compression
from v$im_column_level;
OWNER      TABLE_NAME      COLUMN_NAME        INMEMORY_COMPRESSION
---------- --------------- ------------------ ----------------------
SCOTT      SALES           ID                 NO INMEMORY
SCOTT      SALES           STOREID            FOR CAPACITY LOW
SCOTT      SALES           ITEMID             FOR CAPACITY LOW
SCOTT      SALES           SALESCNT           FOR CAPACITY LOW
SCOTT      SALES           TXT                NO INMEMORY
SCOTT      SALES           SALESDATE          FOR CAPACITY LOW

-- この状態でDML 発行
SQL> update sales set salescnt=99 where rownum <= 1000000;
SQL> commit;

-- DML 実行中に別端末からIMC の状態を確認
SQL> select * from v$im_user_segments;
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE         BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_STATU INMEMORY INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESSION       CON_ID
-------------- -------- --------------- ------------- ---------------------- ----------
SALES                 TABLE      USERS          980484096   32804700160           102596608
COMPLETED      HIGH     AUTO            NO DUPLICATE  FOR QUERY LOW                   0

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_STATU     CON_ID
------------ ----------- ---------- -------------- ----------
1MB POOL      3220176896  961544192 POPULATING              0
64KB POOL      788529152   28377088 POPULATING              0
→ Transaction Journal (64KB POOL) の使用量が増加し、再移入が開始されています。

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_STATU     CON_ID
------------ ----------- ---------- -------------- ----------
1MB POOL      3220176896  959447040 POPULATING              0
64KB POOL      788529152   21626880 POPULATING              0
→ 再移入が行われる事でTransaction Journal (64KB POOL) の使用量が減少していきます。

SQL> select * from v$inmemory_area;
POOL         ALLOC_BYTES USED_BYTES POPULATE_STATU     CON_ID
------------ ----------- ---------- -------------- ----------
1MB POOL      3220176896  960495616 DONE                    0
64KB POOL      788529152   21037056 DONE                    0
→ 再移入完了


(→次のページへ続く