3.7 INMEMORY_CLAUSE_DEFAULT パラメータを指定した場合の動作
先にReference Manual でINMEMORY_CLAUSE_DEFAULT パラメータの説明に誤記がある旨記載しましたので、実際に確認してみましょう。
-- 先ずはManual に記載の通り、初期化パラメータファイルに以下の設定を行い、インスタンス
-- を再起動します。
-- INMEMORY_CLAUSE_DEFAULT='INMEMORY MEMCOMPRESS FOR QUERY LOW PRIORITY LOW'
SQL> show parameters clause
NAME TYPE VALUE
------------------------------------ ----------- -----------------------------------------------
inmemory_clause_default string INMEMORY MEMCOMPRESS FOR QUERY LOW PRIORITY LOW
-- 列を指定してIn-Memory 化した場合
SQL> drop table sales2 purge;
SQL> Create table Sales2 (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales2 primary key (id) using index tablespace users
) tablespace users
inmemory priority medium
inmemory memcompress for query high (storeid, salescnt)
no inmemory (txt);
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
begin
select nvl(max(id),0) into ix from sales2;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..20 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)),
vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/
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 38207488 213909504 0
COMPLETED MEDIUM AUTO NO DUPLICATE FOR QUERY LOW 0
→ セグメント単位ではないので、このView のINMEMORY_COMPRESSION は無視
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 38797312 DONE 0
64KB POOL 788529152 327680 DONE 0
SQL> select owner, table_name, column_name, inmemory_compression
from v$im_column_level;
OWNER TABLE_NAME COLUMN_NAM INMEMORY_COMPRESSION
---------- ---------- ---------- --------------------------
SCOTT SALES2 ID DEFAULT
SCOTT SALES2 STOREID FOR QUERY HIGH
SCOTT SALES2 ITEMID DEFAULT
SCOTT SALES2 SALESCNT FOR QUERY HIGH
SCOTT SALES2 TXT NO INMEMORY
SCOTT SALES2 SALESDATE DEFAULT
→ NO INMEMORY 指定した列 (TXT) はNO INMEMORY のまま
-- セグメントを指定してIn-Memory 化した場合
SQL> drop table sales2 purge;
SQL> Create table Sales2 (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales2 primary key (id) using index tablespace users
) tablespace users
no inmemory;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
begin
select nvl(max(id),0) into ix from sales2;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..20 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)),
vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/
SQL> select * from v$im_user_segments;
レコードが選択されませんでした。
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 2097152 DONE 0
64KB POOL 788529152 0 DONE 0
SQL> select owner, table_name, column_name, inmemory_compression from v$im_column_level;
レコードが選択されませんでした。
→ IMC は使用されていない模様
SQL> select table_name, inmemory, inmemory_priority, inmemory_compression
from user_tables
where table_name = 'SALES2';
TABLE_NAME INMEMORY INMEMO INMEMORY_COMPRESSION
---------- -------- ------ --------------------------
SALES2 DISABLED
Alter table 文又はCreate table 文でINMEMORY のみ指定して、優先レベルや圧縮属性を指定しなかった場合、INMEMORY_CLAUSE_DEFAULT パラメータの設定によって以下のように設定されます。
・INMEMORY_CLAUSE_DEFAULT パラメータが未設定の場合
システムのDefault である、Priority None, Memcompress for query low が設定されます。
・INMEMORY_CLAUSE_DEFAULT パラメータが設定されている場合
INMEMORY_CLAUSE_DEFAULT に指定されている値が設定されます。
それでは実際に、上記の動作を確認してみましょう。
-- INMEMORY_CLAUSE_DEFAULT の確認
SQL> show parameters clause
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_clause_default string
-- テーブル作成/設定値確認
SQL> Create table tab1 (id number(8)) inmemory priority high memcompress for query high;
SQL> select table_name, inmemory, inmemory_priority, inmemory_compression
from user_tables where table_name = 'TAB1';
TABLE_NAME INMEMORY INMEMORY INMEMORY_COMPRESS
---------- -------- -------- -----------------
TAB1 ENABLED HIGH FOR QUERY HIGH
→ Create table で指定した値に設定されています。
-- 優先レベル, 圧縮属性を指定せずにinmemory の再設定/確認
SQL> alter table tab1 inmemory;
SQL> select table_name, inmemory, inmemory_priority, inmemory_compression
from user_tables where table_name = 'TAB1';
TABLE_NAME INMEMORY INMEMORY INMEMORY_COMPRESS
---------- -------- -------- -----------------
TAB1 ENABLED NONE FOR QUERY LOW
→ システムのDefault であるPriority None, Memcompress for query low に変更されています。
-- inmemory_clause_default の変更/確認
SQL> alter system set inmemory_clause_default= 'INMEMORY MEMCOMPRESS FOR DML PRIORITY LOW';
SQL> show parameters clause
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------------------
inmemory_clause_default string INMEMORY MEMCOMPRESS FOR DML PRIORITY LOW
-- 優先レベル, 圧縮属性を指定せずにinmemory の再設定/確認
SQL> alter table tab1 inmemory;
SQL> select table_name, inmemory, inmemory_priority, inmemory_compression
from user_tables where table_name = 'TAB1';
TABLE_NAME INMEMORY INMEMORY INMEMORY_COMPRESS
---------- -------- -------- -----------------
TAB1 ENABLED LOW FOR DML
→ inmemory_clause_default の値に設定値が上書きされました。
3.8 表領域にIn-Memory Option のDefault 値を設定した場合
これまでTable 作成時に直接In-Memory Option のパラメータを指定してきましたが、予め表領域にDefault のIn-Memory Option を設定しておき、該当の表領域にTable が作成された時にDefault 値を反映させる事も可能です。但し既存のテーブルを該当表領域に移動しても、表領域のDefault に設定したIn-Memory 属性は強制されません。
それでは実際に、確認してみましょう。
-- In-Memory 属性を指定した表領域の作成/確認
-- 非RAC 環境の場合、表領域のDefault 句に指定できるのは、圧縮指定とPriority のみ
SQL> Create tablespace imtbs1 datafile '/add_disk2/oradata/ora121/imtbs1.dbf'
size 1024m autoextend off
default inmemory memcompress for query high priority high;
SQL> select tablespace_name, def_inmemory, def_inmemory_priority, def_inmemory_compression
from dba_tablespaces
where tablespace_name = 'IMTBS1';
TABLESPACE_NAME DEF_INME DEF_INME DEF_INMEMORY_COMP
--------------- -------- -------- -----------------
IMTBS1 ENABLED HIGH FOR QUERY HIGH
-- In-Memory 属性を指定した表領域にテーブル作成/データセット
SQL> drop table Sales2 purge;
SQL> Create table Sales2 (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales2 primary key (id) using index tablespace imtbs1
) tablespace imtbs1;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
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)),
vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/
-- データ投入中に別セッションから状態を確認
SQL> select * from v$im_user_segments;
レコードが選択されませんでした。
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 2097152 POPULATING 0
64KB POOL 788529152 5505024 POPULATING 0
→ データを投入するだけで、IMC への移入が開始されている。
-- 数分後 (データ投入中) に再度状態を確認
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
---------- ------ --------------- ------------- ----------------- ----------
SALES2 TABLE IMTBS1 5439488 335544320 283910144
STARTED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 0
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 7340032 POPULATING 0
64KB POOL 788529152 4390912 POPULATING 0
-- Insert 完了後
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
---------- ------ --------------- ------------- ----------------- ----------
SALES2 TABLE IMTBS1 27721728 536870912 309166080
STARTED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 0
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 29360128 POPULATING 0
64KB POOL 788529152 458752 POPULATING 0
-- 移入完了後
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
---------- ------ --------------- ------------- ----------------- ----------
SALES2 TABLE IMTBS1 66977792 536870912 0
COMPLETED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 0
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 68157440 DONE 0
64KB POOL 788529152 917504 DONE 0
-- 既存のテーブルを該当表領域に移動した際の動作を確認
-- In-Memory 属性を指定せず、Table 再作成
SQL> drop table Sales2 purge;
SQL> Create table Sales2 (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales2 primary key (id) using index tablespace users
) tablespace users;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
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)),
vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/
-- データ投入完了後、状態を確認
SQL> select * from v$im_user_segments;
レコードが選択されませんでした。
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 3220176896 2097152 DONE 0
64KB POOL 788529152 0 DONE 0
SQL> select table_name, tablespace_name, inmemory, inmemory_priority, inmemory_compression
from user_tables
where table_name = 'SALES2';
TABLE_NAME TABLESPACE INMEMORY INMEMO INMEMORY_COMPRESS
--------------- ---------- -------- ------ -----------------
SALES2 USERS DISABLED
-- Table をIn-Memory 属性を指定した表領域に移動/状態確認
SQL> alter table sales2 move tablespace IMTBS1;
SQL> select table_name, tablespace_name, inmemory, inmemory_priority, inmemory_compression
from user_tables
where table_name = 'SALES2';
TABLE_NAME TABLESPACE INMEMORY INMEMO INMEMORY_COMPRESS
--------------- ---------- -------- ------ -----------------
SALES2 IMTBS1 DISABLED
→ 表領域は移動しましたが、INMEMORY はDISABLE のままです。
該当の表領域に作成された訳ではないため、既存の設定が優先されています。
-- 一旦表領域を戻して、再度表領域の移動とIn-Memory 属性の指定を同時に行ってみます。
SQL> alter table sales2 move tablespace users;
SQL> alter table sales2 move tablespace imtbs1 inmemory priority low;
SQL> select table_name, tablespace_name, inmemory, inmemory_priority, inmemory_compression
from user_tables
where table_name = 'SALES2';
TABLE_NAME TABLESPACE INMEMORY INMEMO INMEMORY_COMPRESS
--------------- ---------- -------- ------ -----------------
SALES2 IMTBS1 ENABLED LOW FOR QUERY LOW
→ 表領域は移動して、Alter table 文で指定したIn-Memory 属性 (優先度) が設定されました。
圧縮属性については表領域のDefault ではなく、システムのDefault が設定されています。
-- 移入状況確認
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
---------- ------ --------------- ------------- ----------------- ----------
SALES2 TABLE IMTBS1 95092736 545259520 0
COMPLETED LOW 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 96468992 DONE 0
64KB POOL 788529152 720896 DONE 0
→ IMC への移入も行われました。
-- Table の表領域を移動したので、索引のRebuild
SQL> select index_name, status from user_indexes where status != 'VALID';
INDEX_NAME STATUS
--------------- ----------
PK_SALES2 UNUSABLE
SQL> alter index pk_sales2 rebuild;
SQL> select index_name, status from user_indexes where status != 'VALID';
レコードが選択されませんでした。
3.9 Multitenant Architecture との併用
前節までは非Multitenant Architecture 環境でIn-Memory Option の動作確認を行ってきました。In-Memory Option はOracle 12c のもう一つの目玉機能であるMultitenant Architecture との併用が可能です。Multitenant Architecture と併用した場合、In-Memory Option の動作は以下のようになります。
[Multitenant Architecture 環境下でのIn-Memory Option の動作]
・メモリ領域 (IMC), プロセス等は全てCDB が持つ
・INMEMORY_SIZE パラメータは、CDB/各PDB で指定可能
・IMC はCDB のINMEMORY_SIZE パラメータで指定されたサイズで作成される。
・各PDB は、PDB毎のINMEMORY_SIZE で指定したサイズまで、IMC を使用できる。
PDBのINMEMORY_SIZE パラメータを0 に設定すると、該当のPDB ではIMC が使用不可になる。
・各PDB のINMEMORY_SIZE の合計がCDB のINMEMORY_SIZE を超えても構わない。
それでは実際に確認してみましょう。
-- Multitenant Architecture 環境の準備
-- 以下のMultitenant Architecture 環境 を作成しました。
$ sqlplus "/ as sysdba"
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB01 READ WRITE NO
4 PDB02 READ WRITE NO
5 PDB03 READ WRITE NO
PDB01 ~ PDB03 の各PDB には、以下の設定を行っています。
・USERS 表領域の作成
・DBA 権限を持った scott ユーザの作成
-- 接続先の確認
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT ← Container Database に接続中
-- Container DB のINMEMORY_SIZE パラメータの設定
SQL> alter system set inmemory_size=1024M scope=spfile;
-- 一旦インスタンスを再起動して、CDB の設定を反映させる。
SQL> shutdown immediate
SQL> startup
SQL> alter pluggable database all open read write;
SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
3 PDB01 READ WRITE NO
4 PDB02 READ WRITE NO
5 PDB03 READ WRITE NO
-- 各PDB に接続してinmemory_size パラメータを設定
-- PDB では、CDBのinmemory_size 以下の範囲で動的にinmemory_size を変更できる
-- CDB で指定するinmemory_size パラメータは64KB Pool の領域を含んだサイズだが、
-- PDB で指定するinmemory_size パラメータは1MB Pool のサイズとなる。
-- PDB の inmemory_size パラメータには、CDB の1MB Pool サイズを超える値を指定可能だが
-- CDB の1MB Pool のサイズを超えてIMC を使用する事はできない。
SQL> alter session set container=pdb$seed;
SQL> alter system set inmemory_size=0;
SQL> alter session set container=pdb01;
SQL> alter system set inmemory_size=640M;
SQL> alter session set container=pdb02;
SQL> alter system set inmemory_size=640M;
-- CDB のInmemory_size を超える値は設定できない
SQL> alter session set container=pdb03;
SQL> alter system set inmemory_size=1100M;
ORA-02097: 指定した値が無効なので、パラメータを変更できません。 ORA-02095:
指定した初期化パラメータを変更できません。
SQL> alter system set inmemory_size=0;
CDB/各PDB に設定されているパラメータを確認
SQL> alter session set container=cdb$root;
SQL> select con_id, name, value from v$system_parameter where name='inmemory_size';
CON_ID NAME VALUE
---------- -------------------- --------------------
0 inmemory_size 1073741824 ← DB全体に対しての設定
2 inmemory_size 0 ← PDB$SEED に対しての設定
3 inmemory_size 671088640 ← PDB01 に対しての設定
4 inmemory_size 671088640 ← PDB02 に対しての設定
5 inmemory_size 0 ← PDB03 に対しての設定
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
------------ ----------- ---------- --------------- ----------
1MB POOL 854589440 0 DONE 1 ←CDB$ROOT への割当て
64KB POOL 201326592 0 DONE 1
1MB POOL 854589440 0 DONE 2 ←PDB$SEED への割当て
64KB POOL 201326592 0 DONE 2
1MB POOL 854589440 0 DONE 3 ←PDB01 への割当て
64KB POOL 201326592 0 DONE 3
1MB POOL 854589440 0 DONE 4 ←PDB02 への割当て
64KB POOL 201326592 0 DONE 4
1MB POOL 854589440 0 DONE 5 ←PDB03 への割当て
64KB POOL 201326592 0 DONE 5
→ 見かけ上、全てのDB に1024MB のIMU が割り当てられているように見えます。
-- PDB にテーブルを作成してIn-Memory 化してみる。
SQL> connect scott/tiger@pdb01
SQL> show con_name
CON_NAME
------------------------------
PDB01
SQL> Create table Sales (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales primary key (id) using index tablespace users
) tablespace users;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
begin
select nvl(max(id),0) into ix from sales;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..50 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> alter table sales 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_STATUS INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
--------------- ------ --------------- ------------- ----------------- ----------
SALES TABLE USERS 66781184 536870912 0
COMPLETED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 3
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
------------ ----------- ---------- --------------- ----------
1MB POOL 854589440 66060288 DONE 3
-- Container DB から状態を確認
SQL> conn / as sysdba
SQL> select * from v$im_segments;
OWNER SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE BYTES
---------- ---------- ---------- ---------- ---------- ------------- -------------
BYTES_NOT_POPULATED POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
------------------- ---------- ------ --------------- ------------- ----------------- ----------
SCOTT SALES TABLE USERS 66781184 536870912
0 COMPLETED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 3
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 854589440 66060288 DONE 1
64KB POOL 201326592 720896 DONE 1
1MB POOL 854589440 66060288 DONE 2
64KB POOL 201326592 720896 DONE 2
1MB POOL 854589440 66060288 DONE 3
64KB POOL 201326592 720896 DONE 3
1MB POOL 854589440 66060288 DONE 4
64KB POOL 201326592 720896 DONE 4
1MB POOL 854589440 66060288 DONE 5
64KB POOL 201326592 720896 DONE 5
→ v$im_segments からはCON_ID 列でどのPDB がIMC を使用しているか分かるが
v$inmemory_area からは分からない。
別のPDB (PDB02) でもやってみる。
SQL> connect scott/tiger@pdb02
SQL> show con_name
CON_NAME
------------------------------
PDB02
SQL> select * from v$im_user_segments;
レコードが選択されませんでした。
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 854589440 66060288 DONE 4
64KB POOL 201326592 720896 DONE 4
SQL> Create table Sales (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales primary key (id) using index tablespace users
) tablespace users;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
begin
select nvl(max(id),0) into ix from sales;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..70 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> alter table sales 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_COMPRESS CON_ID
---------- ------ --------------- ------------- ----------------- ----------
SALES TABLE USERS 633339904 754974720 42254336
COMPLETED HIGH AUTO NO DUPLICATE NO MEMCOMPRESS 4
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 854589440 722468864 DONE 4
64KB POOL 201326592 3866624 DONE 4
-- PDB02 に設定したinmemory_size に達したため、bytes_not_populated が0になる前に
-- Populate が完了している。
-- 但し、1MB Pool を使い切った訳では無いので、v$inmemory_area のPopulate_status も
-- Out of Memory にはなっていない
-- alert log には、以下の警告が出ている。
-- Insufficient memory to populate table to inmemory area
-- 再度Container DB から確認
SQL> conn / as sysdba
SQL> select * from v$im_segments;
OWNER SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE BYTES
---------- ---------- ---------- ---------- ---------- ------------- -------------
BYTES_NOT_POPULATED POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
------------------- ---------- ------ --------------- ------------- ----------------- ----------
SCOTT SALES TABLE USERS 66781184 536870912
0 COMPLETED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 3
SCOTT SALES TABLE USERS 633339904 754974720
42254336 COMPLETED HIGH AUTO NO DUPLICATE NO MEMCOMPRESS 4
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 854589440 722468864 DONE 1
64KB POOL 201326592 3866624 DONE 1
1MB POOL 854589440 722468864 DONE 2
64KB POOL 201326592 3866624 DONE 2
1MB POOL 854589440 722468864 DONE 3
64KB POOL 201326592 3866624 DONE 3
1MB POOL 854589440 722468864 DONE 4
64KB POOL 201326592 3866624 DONE 4
1MB POOL 854589440 722468864 DONE 5
64KB POOL 201326592 3866624 DONE 5
-- PDB02 はPDB に設定したInmemory_size に達してしまったが、PDB01 はまだ余裕があるので
-- 追加のテーブルを作成してIn-Memory 化してみる。
SQL> conn scott/tiger@pdb01
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_S CON_ID
------------ ----------- ---------- ---------- ----------
1MB POOL 854589440 722468864 DONE 3
64KB POOL 201326592 3866624 DONE 3
SQL> Create table Sales2 (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk2_sales primary key (id) using index tablespace users
) tablespace users;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
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)),
vtxt, sysdate - trunc(dbms_random.value(1, 100))
from dual connect by level <= roff;
ix := ix + roff;
commit;
end loop;
end;
/
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_COMPRESS CON_ID
---------- ------ --------------- ------------- ----------------- ----------
SALES2 TABLE USERS 1245184 536870912 516169728
STARTED HIGH AUTO NO DUPLICATE FOR CAPACITY HIGH 3
SALES TABLE USERS 66781184 536870912 0
COMPLETED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 3
SQL> /
SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE BYTES BYTES_NOT_POPULATED
---------- ---------- ---------- ---------- ------------- ------------- -------------------
POPULATE_S INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
---------- ------ --------------- ------------- ----------------- ----------
SALES2 TABLE USERS 39518208 536870912 0
COMPLETED HIGH AUTO NO DUPLICATE FOR CAPACITY HIGH 3
SALES TABLE USERS 66781184 536870912 0
COMPLETED HIGH AUTO NO DUPLICATE FOR QUERY HIGH 3
--> PDB01 はOk
-- PDB03 は、inmemory_size=0 の設定なので、IMCは使用されない。
SQL> connect scott/tiger@pdb03
SQL> show con_name
CON_NAME
------------------------------
PDB03
SQL> show parameters inmemory_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
inmemory_size big integer 0
SQL> Create table Sales (
id number(12),
StoreID number(4),
ItemID number(8),
SalesCnt number(6),
txt varchar2(64),
SalesDate date,
constraint pk_sales primary key (id) using index tablespace users
) tablespace users;
SQL> declare
ix pls_integer;
roff constant pls_integer := 100000;
vtxt constant varchar2(64) := dbms_random.string('p', 64);
begin
select nvl(max(id),0) into ix from sales;
dbms_random.seed(to_char(systimestamp));
for v1 in 1..10 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> alter table sales inmemory priority high
memcompress for capacity high;
-- 10分待機
SQL> select * from v$im_user_segments;
レコードが選択されませんでした。
--> システム全体としてIn-Memory は有効化されているので、Alter table 文は成功するが、
以上でCDB に割当てられたIMC を、複数のPDB がPDB 毎の利用制限に従って利用できる事が確認できました。それでは最後に、PDB がCDB に割当てられたIMCを使い切ってしまった場合の動作を確認してみましょう。
SQL> connect / as sysdba
SQL> select con_id, owner, table_name from cdb_tables where inmemory = 'ENABLED';
CON_ID OWNER TABLE_NAME
------ ---------- ----------
3 SCOTT SALES2
3 SCOTT SALES
4 SCOTT SALES
5 SCOTT SALES
SQL> connect scott/tiger@pdb01
SQL> alter table sales no inmemory;
SQL> SQL> alter table sales2 no inmemory;
SQL> connect scott/tiger@pdb02
SQL> alter table sales no inmemory;
SQL> connect scott/tiger@pdb03
SQL> alter table sales no inmemory;
-- PDB03 でIMC が使用できるよう設定
SQL> alter system set inmemory_size = 512m;
SQL> connect / as sysdba
SQL> select con_id, owner, table_name from cdb_tables where inmemory = 'ENABLED';
レコードが選択されませんでした。
SQL> select con_id, name, value from v$system_parameter where name='inmemory_size';
CON_ID NAME VALUE
------ -------------------- --------------------
0 inmemory_size 1073741824
2 inmemory_size 0
3 inmemory_size 671088640
4 inmemory_size 671088640
5 inmemory_size 536870912
SQL> select * from v$im_segments;
レコードが選択されませんでした
SQL> connect scott/tiger@pdb01
SQL> alter table sales inmemory priority low no memcompress;
SQL> connect scott/tiger@pdb02
SQL> alter table sales inmemory priority low no memcompress;
SQL> connect / as sysdba
SQL> select * from v$im_segments;
OWNER SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE BYTES
---------- ---------- ---------- ---------- ---------- ------------- -------------
BYTES_NOT_POPULATED POPULATE_STATUS INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
------------------- --------------- ------ --------------- ------------- ----------------- ------
SCOTT SALES TABLE USERS 426967040 536870912
56705024 STARTED LOW AUTO NO DUPLICATE NO MEMCOMPRESS 3
SQL> select * from v$im_segments;
POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- ----------- ---------- --------------- ------
1MB POOL 854589440 441450496 POPULATING 1
64KB POOL 201326592 2293760 POPULATING 1
1MB POOL 854589440 441450496 DONE 2
64KB POOL 201326592 2293760 DONE 2
1MB POOL 854589440 441450496 POPULATING 3
64KB POOL 201326592 2293760 POPULATING 3
1MB POOL 854589440 441450496 POPULATING 4
64KB POOL 201326592 2293760 POPULATING 4
1MB POOL 854589440 441450496 POPULATING 5
64KB POOL 201326592 2293760 POPULATING 5
SQL> select * from v$im_segments;
OWNER SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE BYTES
---------- ---------- ---------- ---------- ---------- ------------- -------------
BYTES_NOT_POPULATED POPULATE_STATUS INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
------------------- --------------- ------ --------------- ------------- ----------------- ------
SCOTT SALES TABLE USERS 476446720 536870912
0 COMPLETED LOW AUTO NO DUPLICATE NO MEMCOMPRESS 3
SCOTT SALES TABLE USERS 354091008 754974720
345907200 COMPLETED LOW AUTO NO DUPLICATE NO MEMCOMPRESS 4
SQL> select * from v$inmemory_area;
POOL ALLOC_BYTES USED_BYTES POPULATE_STATUS CON_ID
---------- ----------- ---------- --------------- ------
1MB POOL 854589440 854589440 OUT OF MEMORY 1
64KB POOL 201326592 4259840 DONE 1
1MB POOL 854589440 854589440 OUT OF MEMORY 2
64KB POOL 201326592 4259840 DONE 2
1MB POOL 854589440 854589440 OUT OF MEMORY 3
64KB POOL 201326592 4259840 DONE 3
1MB POOL 854589440 854589440 OUT OF MEMORY 4
64KB POOL 201326592 4259840 DONE 4
1MB POOL 854589440 854589440 OUT OF MEMORY 5
64KB POOL 201326592 4259840 DONE 5
→ IMC の1MB POOL を使い切りました。
SQL> connect scott/tiger@pdb03
SQL> alter table sales inmemory priority high
memcompress for query high;
-- 10分待機
SQL> select * from v$im_segments;
レコードが選択されませんでした。
-- In-Memory 化できなかったTable にアクセスしてみる。
SQL> select min(salesdate), max(salesdate), count(*) from sales where storeid=10;
MIN(SALE MAX(SALE COUNT(*)
-------- -------- ----------
15-01-01 15-04-09 9966
SQL> select min(salesdate), max(salesdate), count(*) from sales where storeid=25;
MIN(SALE MAX(SALE COUNT(*)
-------- -------- ----------
15-01-01 15-04-09 10048
-- 再度IMC の状態を確認
SQL> select * from v$im_segments;
レコードが選択されませんでした。
-- Container DB からも確認してみる
SQL> connect / as sysdba
SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT
SQL> select * from v$im_segments;
OWNER SEGMENT_NA PARTITION_ SEGMENT_TY TABLESPACE INMEMORY_SIZE BYTES
---------- ---------- ---------- ---------- ---------- ------------- -------------
BYTES_NOT_POPULATED POPULATE_STATUS INMEMO INMEMORY_DISTRI INMEMORY_DUPL INMEMORY_COMPRESS CON_ID
------------------- --------------- ------ --------------- ------------- ----------------- ------
SCOTT SALES TABLE USERS 476446720 536870912
0 COMPLETED LOW AUTO NO DUPLICATE NO MEMCOMPRESS 3
SCOTT SALES TABLE USERS 354091008 754974720
345907200 COMPLETED LOW AUTO NO DUPLICATE NO MEMCOMPRESS 4[ご参考] CDB/PDB の接続で使用した、tnsnames.ora/listener.ora
Multitenant Architecture では、tnsnames.ora にSERVICE_NAME にPDB名を指定した接続文字列に指定する事で、任意のPDB に接続する事ができます。ここでは、ご参考までに本検証で使用したtnsnames.ora, listener.ora を記載します。
※ ora12102 はDB Server のホスト名です。
$ cd $ORACLE_HOME/network/admin
$ cat tnsnames.ora
# Container DB への接続文字列
cdb =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = ora12102)(PORT = 1521))
(CONNECT_DATA = (SID = ora121))
)
# Pluggable DB (PDB01) への接続文字列
pdb01 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = ora12102)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = pdb01))
)
# Pluggable DB (PDB02) への接続文字列
pdb02 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = ora12102)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = pdb02))
)
# Pluggable DB (PDB03) への接続文字列
pdb03 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = ora12102)(PORT = 1521))
(CONNECT_DATA = (SERVICE_NAME = pdb03))
)
$ cat listener.ora
LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = ora12102)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)
4. まとめ
以上でIn-Memory Option について一通りの確認ができました。In-Memory Option を使用すると、DWH 系の処理を大幅に高速化する事ができます。更に、DWH 用に定義されていた索引が不要になるため、OLTP 系の処理性能向上も期待できます。またIMCU はBuffer Cache との一貫性が保障されているため、常に最新のデータで分析処理を行わせる事が可能です。しかし稀に、最新データではなく静止点を決めて分析処理を行わせたい場合もあるでしょう。そのような場合は、Materialized View を対象にして分析処理を行う事で、同じDatabase 内に静止点を作成する事も可能です。In-Memory Option を使用する事で、基幹系のシステムとDWH 系のシステムを1つのDatabase に集約できる可能性も出てきました。更にIn-Memory Option は、Oracle 12c のDatabase 集約機能であるMultitenant Architecture との併用も可能ですので、Database の集約効率の更なる向上も期待できます。
今回見てきた通り、In-Memory Option の導入は非常に簡単ですが、導入効果は非常に大きいと言えます。性能が出ないDWH アプリケーションでお悩みの方は、一度In-Memory Option を試してみては如何でしょうか?
参考情報
In-Memory Option の概要
http://www.oracle.com/technetwork/jp/database/in-memory/overview/index.html
http://www.oracle.com/technetwork/jp/database/articles/pickup/database-in-memory-2283690-ja.html
In-Memory Option ホワイト・ペーパー
http://www.oracle.com/technetwork/jp/database/in-memory/overview/twp-oracle-database-in-memory-2245633-ja.pdf
Oracle 12.1.0.2 Core Tech セミナー
http://www.oracle.com/technetwork/jp/ondemand/od12c-coretech-aug2014-2283256-ja.html
http://www.oracle.com/webfolder/technetwork/jp/ondemand/od12c-aug2014/09-DB12102-coretech-DBIM-population-v1.pdf
Oracle 12.1.0.2 新機能概要
https://blogs.oracle.com/otnjp/entry/database_12c_new_feature
Oracle 12.1.0.2 管理者ガイド
https://docs.oracle.com/cd/E57425_01/121/ADMIN/memory.htm#BABHGBGE
Oracle 12.1.0.2 Database SQL 言語リファレンス
http://docs.oracle.com/cd/E57425_01/121/SQLRF/toc.htm
Oracle 12.1.0.2 Database リファレンス
http://docs.oracle.com/cd/E57425_01/121/REFRN/toc.htm
Oracle 12.1.0.2 Database PL/SQL パッケージおよびタイプ・リファレンス
http://docs.oracle.com/cd/E57425_01/121/ARPLS/toc.htm