対応バージョン

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の値がいつまでも残ったままとなることが確認できました。