対応バージョン
Oracle Database 12.1.0.2
更新履歴
| 日付 | 更新概要 |
|---|---|
| 2016/06/23 | 記事公開 |
Database In-Memoryのデータのポピュレーションについて、メモリ上に乗り切らない場合の動作について説明します。(ポピュレーションとは、物理ディスクからインメモリ用のメモリ領域にデータを移入する処理です。)
データの準備
メモリ領域の準備
インメモリに入れるデータの準備を行います。
初期化パラメータにて、100MBのメモリ領域を指定しています。
SQL> alter system set inmemory_size = 100M scope=spfile;
SQL> alter system set inmemory_clause_default = 'INMEMORY MEMCOMPRESS FOR QUERY LOW PRIORITY MEDIUM' scope=spfile;
SQL> shutdown immediate
SQL> startupテストユーザの準備
TESTという名前のユーザを作成し、INMEMというテーブルをインメモリ化することでテストを行います。データは適当にDBA_TABELSのデータを増幅しています。
SQL> create user TEST identified by test default tablespace USERS;
SQL> grant create session to TEST;
SQL> grant unlimited tablespace to TEST;
SQL> grant create table to TEST;
SQL>
SQL> create table TEST.INMEM as select * from DBA_TABLES inmemory;
SQL> column OWNER format a10
SQL> column TABLE_NAME format a30
SQL> column TABLESPACE_NAME format a15
SQL> select OWNER
2 , TABLE_NAME
3 , TABLESPACE_NAME
4 , INMEMORY
5 , INMEMORY_PRIORITY
6 from DBA_TABLES
7 where owner = 'TEST'
8 and table_name = 'INMEM';
OWNER TABLE_NAME TABLESPACE_NAME INMEMORY INMEMORY
---------- ------------------------------ --------------- -------- --------
TEST INMEM USERS ENABLED MEDIUM
データのインメモリ化確認
作成後の状態です。データが少ないためすぐにポピュレーションが完了し、メモリ上にデータが移入されていることが確認できます。
SQL> set line 180 trim on pages 10000
SQL> column SEGMENT_NAME format a30
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 1.125 2 0 FOR QUERY LOW
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 1 DONE
64KB POOL 16 .125 DONE
データの追加時の変化の確認
データの追加を行なった際の変化を確認します。
SQL> insert into TEST.INMEM select * from TEST.INMEM;
SQL> commit;
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 20.375 629 309.78125 FOR QUERY LOW
SQL> -- MBYTES_NOT_POPULATED が増加し、ポピュレーションが終わっていないデータが存在することが確認できます。
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 20 DONE
64KB POOL 16 .375 DONE
SQL> -- V$INMEMORY_AREA の POPULATE_STATUS は変化せず、 DONE のままです。2分毎にトリクル再移入(自動的に差分のポピュレーションを行う処理)を行っているため、2分間待ちます。
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 37.5 629 0 FOR QUERY LOW
SQL> -- MBYTES_NOT_POPULATED が 0 となっていることが確認できます。
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 37 DONE
64KB POOL 16 .5 DONE
SQL> -- POPULATE_STATUS に変化はありませんが、 USED_MBYTES についても増加しています。
DBMS_INMEMORY.POPULATEを実行し、手動によるポピュレーション処理を実施します。
SQL> insert into TEST.INMEM select * from TEST.INMEM;
SQL> commit;
SQL> exec DBMS_INMEMORY.POPULATE('TEST', 'INMEM');
PL/SQL procedure successfully completed.
SQL> -- ポピュレーション完了を待たずに、即操作が戻ります。
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 41.6875 1284 447.023438 FOR QUERY LOW
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 38 POPULATING
64KB POOL 16 .625 POPULATING
SQL> -- POPULATE_STATUS が POPULATING に変化しています。(完了したら DONE に変化します)メモリ設定を超えたデータが投入された場合の確認
さらにデータを追加し、メモリサイズ以上のデータを投入します。
SQL> insert into TEST.INMEM select * from TEST.INMEM;
SQL> commit;
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 75.9375 1796 511.5 FOR QUERY LOW
SQL> -- しばらくたっても MBYTES_NOT_POPULATED が変化しません。
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 75 DONE
64KB POOL 16 .9375 DONE
SQL> -- 手動でポピュレーションをしてみます。
SQL> exec DBMS_INMEMORY.POPULATE('TEST', 'INMEM');
PL/SQL procedure successfully completed.
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 75.9375 1796 511.5 FOR QUERY LOW
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 77 DONE
64KB POOL 16 .9375 DONE
SQL> -- 特に変化が起きません。
INMEMORY化を一度解除し、再度メモリに載せます。これにより、OUT OF MEMORYのステータスとなることを確認します。
SQL> -- インメモリ対象から一度除外
SQL> alter table TEST.INMEM no inmemory;
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
no rows selected
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 0 DONE
64KB POOL 16 0 DONE
SQL> -- 再度メモリ化
SQL> alter table TEST.INMEM inmemory;
SQL> -- ポピュレーション開始
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
no rows selected
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 0 POPULATING
64KB POOL 16 0 POPULATING
SQL> -- 少し時間がたつと、 POPULATE_STATUS が STARTED となりポピュレーション開始
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS STARTED 49.5 1796 913.570313 FOR QUERY LOW
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 58 POPULATING
64KB POOL 16 .5625 POPULATING
SQL> -- さらに待つと、V$IM_SEGMENTS の POPULATE_STATUS が STARTED から COMPLETED に変化
SQL> select OWNER
2 , SEGMENT_NAME
3 , TABLESPACE_NAME
4 , POPULATE_STATUS
5 , INMEMORY_SIZE / 1024 / 1024 as MBYTES_INMEMORY
6 , BYTES / 1024 / 1024 as MBYTES_POPULATED
7 , BYTES_NOT_POPULATED / 1024 / 1024 as MBYTES_NOT_POPULATED
8 , INMEMORY_COMPRESSION
9 from V$IM_SEGMENTS
10 order by 1,2;
OWNER SEGMENT_NAME TABLESPACE_NAME POPULATE_ MBYTES_INMEMORY MBYTES_POPULATED MBYTES_NOT_POPULATED INMEMORY_COMPRESS
---------- ------------------------------ --------------- --------- --------------- ---------------- -------------------- -----------------
TEST INMEM USERS COMPLETED 76.625 1796 459.382813 FOR QUERY LOW
SQL> -- V$INMEMORY_AREA の POPULATE_STATUS は "OUT OF MEMORY" となる
SQL> select POOL
2 , ALLOC_BYTES / 1024 / 1024 as ALLOC_MBYTES
3 , USED_BYTES / 1024 / 1024 as USED_MBYTES
4 , POPULATE_STATUS
5 from V$INMEMORY_AREA
6 order by 1;
POOL ALLOC_MBYTES USED_MBYTES POPULATE_STATUS
-------------------------- ------------ ----------- --------------------------
1MB POOL 79 79 OUT OF MEMORY
64KB POOL 16 .625 DONE
OUT OF MEMORY となることを確認できました。こちらの検証から、新規追加時でないとOUT OF MEMORYのステータスとならないことが確認できます。
また、ポピュレーションが終わらない場合はMBYTES_NOT_POPULATEDの値がいつまでも残ったままとなることが確認できました。
