5 IM列ストアの手動での移入

データベースはPRIORITY設定がNONEのインメモリー・オブジェクトを自動的に移入しません。これらのオブジェクトに移入するには、SQLまたはPL/SQLを実行する必要があります。

この章のトピックは、次のとおりです:

5.1 インメモリー・オブジェクトの手動移入について

全表スキャン、DBMS_INMEMORYプログラム・ユニット、またはDBMS_INMEMORY_ADMIN.POPULATE_WAITのいずれかを使用して、手動でオブジェクトを移入します。

PRIORITYNONEに設定してオブジェクトを有効にし、そのオブジェクトをすぐに追加する場合は、次のセクションで説明するオプションを使用できます。

5.1.1 SELECTを使用した移入

表スキャンを強制するSELECT文を発行して、移入を開始できます。

この場合、データベースはオブジェクトの各行を読み取り、それを列形式に変換します。次の文は全表スキャンを保証しません。

SELECT COUNT(*) FROM object

これは、オプティマイザが索引のスキャンを選択するためです。したがって、次の例に示すように、SELECT COUNT(*)問合せの FULLヒントを使用して全表スキャンを強制することをお薦めします。

SELECT /*+ FULL(customers) NO_PARALLEL(customers) */ COUNT(*) FROM customers;

関連項目:

5.1.2 DBMS_INMEMORY.POPULATEを使用した移入

DBMS_INMEMORY.POPULATEプロシージャは、全体スキャンと同じ結果を出します。

データベースは指定されたオブジェクトの各行を読み取り、行形式から列形式に変換して、IM列ストアに移入します。次のPL/SQLブロックは、customer表の移入を開始します。

BEGIN
  DBMS_INMEMORY.POPULATE( schema_name => 'SH', table_name => 'CUSTOMERS');
END;
/

5.1.3 DBMS_INMEMORY_ADMIN.POPULATE_WAITを使用した移入

DBMS_INMEMORY_ADMIN.POPULATE_WAIT関数は、優先度が指定された優先度以上のすべてのINMEMORYオブジェクトの移入を開始し、移入のステータス値を返します。ユーザー指定の間隔は、値がコール元に戻されるまで関数が待機する最大時間を指定します。

オブジェクトが移入されるかどうかを確認する使用例には、次のものが含まれます。

  • データベースが閉じられたら、管理者のみだけがデータベースにアクセスできるようにSTARTUP RESTRICTでデータベースを開き、希望するタイムアウト設定でPOPULATE_WAITを実行します。POPULATE_WAITが、タイムアウトを示す-1を返した場合は、POPULATE_WAITを再実行します。関数が0を返したときに、制限付きセッションを無効にして、管理者以外のユーザーがデータベースに問合せできるようにします。

  • サービスまたはアプリケーション層の手法を使用して、データベース接続をブロックします。分析索引が存在しない場合や、アプリケーションが適切なパフォーマンスを提供するためにIM列ストアに依存している場合は、これらの手法がリソース集中型の問合せを防ぎます。

POPULATE_WAIT関数は、表名を入力として受け入れません。かわりに、ファンクションは指定されたpriority以上のPRIORITY設定(デフォルトはLOW)を使用して、すべてINMEMORYオブジェクトの移入タスクを送信します。優先度がNONEの場合、このファンクションはすべてのINMEMORYオブジェクトの移入を開始します。POPULATE_WAITは、優先度設定のない外部表には適用しません。

関数は移入パーセンテージを入力(デフォルトは100)およびタイムアウト間隔(デフォルトは99999999秒(115.74日))としてを受け入れます。関数を実行すると、データベースは指定されたPRIORITY基準を満たすオブジェクトの移入をタイムアウト間隔内で試行し、次に移入ステータスを示す値を返します。

次の表に、POPULATE_WAITで想定される戻り値を示します。この関数は、timeoutで指定された間隔の終了前に条件が満たされた場合にのみ、値012および3を返します。たとえば、timeout600の場合に、600秒経過する前にメモリー不足エラーが発生した場合にのみ、この関数は1を返します。このファンクションは、データベースがリクエストされた操作を完了するに、タイムアウト間隔が終了になった場合にのみ-1を返します。

表5-1 POPULATE_WAITの戻り値

定数 説明

POPULATE_TIMEOUT

-1

移入の完了を待機中に関数がタイムアウトしました。

現在の移入ジョブは、-1が返された後もバックグラウンドで引き続き実行されます。-1が返された後でPOPULATE_TIMEOUTを再発行すると、移入が再開されます。すでに移入されているセグメントは削除されません。

POPULATE_SUCCESS

0

priority基準を満たすすべてのオブジェクトが、指定した完了のpercentageに移入されました。

POPULATE_OUT_OF_MEMORY

1

インメモリー・プールに、指定した完了のpercentagepriority基準を満たすオブジェクトを移入するための十分なメモリーがありません。

POPULATE_NO_INMEMORY_OBJECTS

2

指定したpriority基準を満たすINMEMORYオブジェクトがありません。

POPULATE_INMEMORY_SIZE_ZERO

3

インメモリー列ストアが有効になっていません。

関連項目:

5.1.4 DBMS_INMEMORY.REPOPULATEを使用した移入

DBMS_INMEMORY.REPOPULATEは、現在IM列ストアに移入されている表、パーティションまたはサブパーティションを強制的に再移入します。

このプロシージャを現在移入されていないインメモリー・オブジェクトに使用する場合、このプロシージャはDBMS_INMEMORY.POPULATEと機能的に同等です。

関連項目:

5.2 インメモリー・オブジェクトの初期移入の強制

全表スキャン、POPULATEプロシージャ、POPULATE_WAIT関数またはREPOPULATEプロシージャを使用して、オブジェクトの移入を強制できます。

前提

このタスクでは、次のことを想定しています。

  • IM列ストアが有効になっている。

  • 表をインメモリー移入できるようにする。

  • IM列ストアへの表の即時移入を強制的に実行する必要がある。

INMEMORY表の移入を強制的に実行するには:

  1. SQL*PlusまたはSQL Developerで、管理者権限を持つユーザーとしてデータベースにログインします。

  2. INMEMORY属性を表に適用します。

    たとえば、次のようにsh.customersをIM移入のために有効にします。

    ALTER TABLE sh.customers INMEMORY;
    

    前述の例では、デフォルトの優先度はNONEです。

  3. 必要な場合は、V$IM_SEGMENTSを問い合せて移入ステータスを確認します。

    たとえば、次の文を使用します(出力例が含まれています)。

    COL OWNER FORMAT a10;
    COL NAME FORMAT a25;
    COL STATUS FORMAT a10;
    
    SELECT OWNER, SEGMENT_NAME NAME,
           POPULATE_STATUS STATUS
    FROM   V$IM_SEGMENTS
    WHERE  SEGMENT_NAME = 'CUSTOMERS';
    
    no rows selected

    上の出力では、オブジェクトがまだIM列ストアに移入されていないことが示されています。

  4. 次のいずれかの方法で移入を開始します。

    • FULLヒントを指定したSELECTを使用して、表のすべての行を問い合せます。

      たとえば、次の文を発行します。

      SELECT /*+ FULL(customers) NO_PARALLEL(customers) */ COUNT(*) FROM sh.customers;
    • DBMS_INMEMORY.POPULATEプロシージャを実行します。

      たとえば、このプロシージャを次のように、sh.customersに対して実行します。

      EXEC DBMS_INMEMORY.POPULATE('SH', 'CUSTOMERS');
    • DBMS_INMEMORY.REPOPULATEプロシージャを実行します。

      移入されていない表の場合、このプロシージャはPOPULATEと機能的に同じです。たとえば、このプロシージャを次のように、sh.customersに対して実行します。

      EXEC DBMS_INMEMORY.REPOPULATE('SH', 'CUSTOMERS');
    • DBMS_INMEMORY_ADMIN.POPULATE_WAIT関数を実行します。

      次のコード例では、PRIORITY設定に関係なく、すべてのINMEMORYオブジェクトを移入します。例では、すべてのオブジェクトが100%移入されるまで関数が待機するように指定します。また、1800秒(30分)以内に正常終了しなかった場合はエラーでタイムアウトする必要があります。

      VARIABLE b_pop_status NUMBER
      BEGIN
         SELECT DBMS_INMEMORY_ADMIN.POPULATE_WAIT(
                  priority   => 'NONE' ,
                  percentage => 100    ,
                  timeout    => 1800   ,
                  force      => FALSE  )
           INTO :b_pop_status
         FROM   dual;
      END;
      /
      PRINT b_pop_status
      
  5. 必要な場合は、移入ステータスを確認するために、V$IM_SEGMENTSを問い合せます。

    たとえば、次の文を使用します(出力例が含まれています)。

    SELECT OWNER, SEGMENT_NAME NAME,
           POPULATE_STATUS STATUS
    FROM   V$IM_SEGMENTS
    WHERE  SEGMENT_NAME = 'CUSTOMERS';
    
    OWN NAME       STATUS
    --- ---------- --------------------
    SH  CUSTOMERS  COMPLETED
    

    これで、表がIM列ストアに移入されました。

関連項目:

5.3 インメモリー表の手動での移入: 例

次の例は、インメモリー表を手動で移入する方法を示しています。

5.3.1 全表スキャンを使用したインメモリー表の移入: 例

この例では、全表スキャンを使用してsh.sales表をIM列ストアに移入します。

管理者としてデータベースにログインし、次のDDL文を発行してsh.sales表にINMEMORY句を追加したと仮定します。

ALTER TABLE sh.sales INMEMORY;

上の文では、INMEMORY句のデフォルトであるMEMCOMPRESS FOR QUERYおよびPRIORITY NONEが使用されます。PRIORITYNONEであるため、データベースは表をIM列ストアに自動的に移入しません。次の問合せは、sh.sales表が現在移入されていないことを確認します。

COL OWNER FORMAT a10;
COL NAME FORMAT a25;
COL STATUS FORMAT a10;

SELECT OWNER, SEGMENT_NAME NAME,
       POPULATE_STATUS STATUS
FROM   V$IM_SEGMENTS
WHERE  SEGMENT_NAME = 'SALES';

no rows selected

次の問合せはFULLヒントを使用してsalesの全表スキャンを強制し、それによって移入を開始します(出力例を含む)。

SELECT /*+ FULL(sales) NO_PARALLEL(sales) */ COUNT(*) FROM sh.sales;

  COUNT(*)
----------
    918843

次の問合せでは、salesの移入ステータスが示されます(出力例が含まれています)。

SET PAGESIZE 50000
COL OWNER FORMAT a3
COL NAME FORMAT a10
COL STATUS FORMAT a20

SELECT OWNER, SEGMENT_NAME NAME, 
       POPULATE_STATUS STATUS
FROM   V$IM_SEGMENTS
WHERE  SEGMENT_NAME = 'SALES';

OWN NAME       STATUS
--- ---------- --------------------
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED
SH  SALES      COMPLETED

16 rows selected.

次の問合せは表の圧縮率を計算します。この問合せは、表がディスク上でさらに圧縮されていないことが前提となります。

COL OWNER FORMAT a5
COL SEGMENT_NAME FORMAT a5
SET PAGESIZE 50000

SELECT v.OWNER, v.SEGMENT_NAME, v.BYTES ORIG_SIZE,
       v.INMEMORY_SIZE IN_MEM_SIZE,
       ROUND(v.BYTES / v.INMEMORY_SIZE, 2) COMP_RATIO
FROM   V$IM_SEGMENTS v
ORDER BY 4;

OWNER SEGME  ORIG_SIZE IN_MEM_SIZE COMP_RATIO
----- ----- ---------- ----------- ----------
SH    SALES     851968     1310720        .65
SH    SALES     835584     1310720        .64
SH    SALES     925696     1310720        .71
SH    SALES     958464     1310720        .73
SH    SALES     950272     1310720        .73
SH    SALES     786432     1310720         .6
SH    SALES     876544     1310720        .67
SH    SALES     753664     1310720        .58
SH    SALES    1081344     1310720        .83
SH    SALES     901120     1310720        .69
SH    SALES     925696     1310720        .71
SH    SALES     933888     1310720        .71
SH    SALES     843776     1310720        .64
SH    SALES     999424     1310720        .76
SH    SALES     581632     1507328        .39
SH    SALES     696320     1507328        .46

16 rows selected.

5.3.2 OPULATEプロシージャを使用した表の移入: 例

この例ではDBMS_INMEMORY.POPULATEを使用して、sh.customers表のIM列ストアへの移入を開始します。

管理者としてデータベースにログインし、次のDDL文を発行してsh.customers表にINMEMORY句を追加したと仮定します。

ALTER TABLE sh.customers INMEMORY;

上の文では、INMEMORY句のデフォルトであるMEMCOMPRESS FOR QUERYおよびPRIORITY NONEが使用されます。PRIORITYNONEであるため、データベースは表をIM列ストアに自動的に移入しません。次の問合せは、sh.customers表が現在移入されていないことを確認します。

COL OWNER FORMAT a10;
COL NAME FORMAT a25;
COL STATUS FORMAT a10;

SELECT OWNER, SEGMENT_NAME NAME,
       POPULATE_STATUS STATUS
FROM   V$IM_SEGMENTS
WHERE  SEGMENT_NAME = 'CUSTOMERS';

no rows selected

次のPL/SQLコードはイニシアティブの移入にPOPULATEプロシージャを使用します。

EXEC DBMS_INMEMORY.POPULATE('SH', 'CUSTOMERS');

次の問合せでは、customersの移入ステータスが示されます(出力例が含まれています)。

SELECT OWNER, SEGMENT_NAME NAME,
       POPULATE_STATUS STATUS
FROM   V$IM_SEGMENTS
WHERE  SEGMENT_NAME = 'CUSTOMERS';

OWN NAME       STATUS
--- ---------- --------------------
SH  CUSTOMERS  COMPLETED

5.3.3 POPULATE_WAIT関数を使用したタイムアウトの設定: 例

この例では、優先度設定に関係なく、DBMS_INMEMORY_ADMIN.POPULATE_WAITを使用してすべてのインメモリー表を移入します。

例5-1 インメモリー移入のタイムアウト間隔の指定

この例では、データベースに様々な優先順位設定のあるインメモリー表が数多く含まれています。目標は、制限付きデータベース・セッションですべてのインメモリー表に100%の完了を移入し、制限付きセッションを無効にして、アプリケーションがインメモリー表現のみの問合せを行うことを保証できるようにすることです。

データベースは停止されていると仮定します。SQL*Plusでアイドル・インスタンスにSYSDBAとして接続し、次のコマンドを実行します(出力例を含む)。

SQL> STARTUP RESTRICT
ORACLE instance started.

Total System Global Area 1157624280 bytes
Fixed Size                  8839640 bytes
Variable Size             754974720 bytes
Database Buffers           16777216 bytes
Redo Buffers                7933952 bytes
In-Memory Area            369098752 bytes
Database mounted.
Database opened.

データベースが開きますが、アクセスできるのは管理ユーザーのみです。SQL*Plusで次の文を実行します(出力例は太字で表示)。

VARIABLE b_pop_status NUMBER

SELECT DBMS_INMEMORY_ADMIN.POPULATE_WAIT(
         priority   => 'NONE' ,
         percentage => 100    ,
         timeout    => 300    )
  INTO b_pop_status
FROM   DUAL;

PRINT b_pop_status
-1

5分後、関数が–1を返します。このコードは、移入か完了するのを待機している間に関数がタイムアウトしたことを示します。5分は、すべてのINMEMORY表を移入するのに十分な長さではありません。タイムアウトを30分に指定して、SELECT文を再実行します。

SELECT DBMS_INMEMORY_ADMIN.POPULATE_WAIT(
         priority   => 'NONE' ,
         percentage => 100    ,
         timeout    => 1800   )
  INTO b_pop_status
FROM   DUAL;

PRINT b_pop_status
0

8分後、この関数は数値0を返します。このコードは、すべての表が完全に移入されていることを示します。制限付きセッションを無効にします。これによりアプリケーションは、インメモリー表現のみにアクセスするという完全な信頼度でインメモリー・オブジェクトの問合せを開始できます。

ALTER SYSTEM DISABLE RESTRICTED SESSION;

5.3.4 DBMS_INMEMORY.POPULATEを使用したインメモリー外部表への移入: 例

この例では、INMEMORYオプションを持つ外部表を移入します。

この例では、sh_sales.csvファイルを使用して、INMEMORYオプションを指定した外部表sh.admin_ext_salesを作成していると仮定します。

admin_ext_sales表はまだ移入されていません。Oracle Database19c以降、全表スキャンでは標準表への移入と同様に外部表が移入されます。ただし、このシナリオでは、DBMS_INMEMORYパッケージを使用して移入の開始を選択します。

ノート:

インメモリーの外部表を問い合せるセッションでは、初期化パラメータQUERY_REWRITE_INTEGRITYstale_toleratedに設定する必要があります。

外部表が変更された場合、IM列ストアからの結果は未定義であることに注意してください。パーティションが(値を削除または追加して)変更された場合も、結果は未定義です。これにより、IMベースとIM以外のスキャンの結果に違いが生じる可能性があります。DBMS_INMEMORY.REPOPULATEを実行してIMストアをリフレッシュし、表データと再同期化できます。

表に移入するには、次のステップを実行します。

  1. ユーザーshとしてログインします。

  2. データベース・セッションでQUERY_REWRITE_INTEGRITYを設定します。

    ALTER SESSION SET QUERY_REWRITE_INTEGRITY=stale_tolerated;
    
  3. 次のPL/SQLプログラムを実行します。

    EXEC DBMS_INMEMORY.POPULATE('SH', 'ADMIN_EXT_SALES');
  4. V$IM_SEGMENTSを問い合せて、移入ステータスを確認します。

    COL OWNER FORMAT a3
    COL NAME FORMAT a15
    COL STATUS FORMAT a9
    
    SELECT OWNER, SEGMENT_NAME NAME, 
           POPULATE_STATUS STATUS
    FROM   V$IM_SEGMENTS;
    
    OWN NAME            STATUS
    --- --------------- ---------
    SH  ADMIN_EXT_SALES COMPLETED

    前述の出力は、admin_ext_sales表が移入されたことを示しています

関連項目:

5.3.5 REPOPULATEプロシージャを使用したインメモリー外部表のリフレッシュ: 例

この例では、現在移入されているインメモリー外部表を再移入します。

この例では、カンマ区切りのフラット・ファイル/tmp/data/sh_sales.csvを使用して、INMEMORYオプションを指定してsh.admin_ext_sales表を作成し、この表をIM列ストアに移入したと仮定します。

次のように、レコードを/tmp/data/sh_sales.csvに追加したとします。

echo "148,8787,23-NOV-01,2,999,1,23.43" >> /tmp/data/sh_sales.csv
内部表とは異なり、外部表は自動再移入メカニズムを使用しません。外部表をリフレッシュするには、次の方法のいずれかを使用する必要があります。
  • DBMS_INMEMORY.REPOPULATEプロシージャをコールします

  • 表をNO INMEMORYとして指定し、それをINMEMORYとして指定して、全表スキャンを実行します

次の例ではREPOPULATEプロシージャを使用して、IM列ストアにadmin_ext_salesを強制的にリフレッシュさせます。

EXEC DBMS_INMEMORY.REPOPULATE('SH', 'ADMIN_EXT_SALES');

関連項目: