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

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

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

PRIORITYNONEに設定してオブジェクトを有効にし、そのオブジェクトをすぐに追加する場合は、問合せまたはPL/SQL呼び出しを使用できます。

6.1.1 手動インメモリー移入の仕組み

移入はオンデマンドまたは優先度ベースのいずれかになります。移入アルゴリズムは、単一インスタンスを使用するかOracle RACを使用するかによっても異なります。

ノート:

  • INMEMORY_AUTOMATIC_LEVELHIGHに設定すると、Oracle Databaseによって、インメモリー移入に対してすべてのオブジェクトが自動的に有効化され、必要に応じて移入および削除されます。手動による移入は必要ありません。

  • 問合せのパフォーマンスが低下しないように、インメモリー移入が完了している場合にのみテキスト列に対して問合せを実行することをお薦めします。
6.1.1.1 インメモリー移入の優先順位付け

DDL文には、移入キューをより細かく制御できるようにするINMEMORY PRIORITY副句が含まれています。

ノート:

INMEMORY PRIORITY副句は、移入の速度ではなく、移入の優先順位を制御します。

優先度レベル設定は、別々の列サブセットではなく、全体の表、パーティションまたはサブパーティションに適用されます。オブジェクト上でINMEMORY属性を設定することは、このオブジェクトがIM列ストアへの移入の候補であることを意味します。データベースでそのオブジェクトがすぐに移入されることを意味するわけではありません。

ノート:

ディスク上のセグメントが64KB以下の場合、IM列ストアに移入されません。したがって、IM列ストアに対して有効になっている小規模データベース・オブジェクトは、移入されないことがあります。

Oracle Databaseでは、次のように優先順位付けが管理されます。

  • オンデマンド移入

    デフォルトでは、INMEMORY PRIORITYパラメータはNONEに設定されています。この場合、データベースでは、オブジェクトは表の全体スキャンを通じてアクセスされるときのみ移入されます。オブジェクトがアクセスされることがないか、索引スキャンまたはROWIDによるフェッチを通じてしかアクセスされない場合は、移入が起こることはありません。

  • 優先度ベース移入

    PRIORITYNONE以外の値に設定されている場合、Oracle databaseでは、内部的に管理される優先順位キーを使用して、オブジェクトが自動的に移入されます。この場合、全体スキャンは、移入に必要な条件ではありません。データベースでは、次のことが実行されます。

    • データベース・インスタンスの再起動後に、列データをIM列ストアに自動的に移入します

    • 指定された優先度レベルに基づいて、INMEMORYオブジェクトの移入を問い合せます

      たとえば、INMEMORY PRIORITY CRITICALで変更された表はINMEMORY PRIORITY HIGHで変更された表よりも優先され、この表もまた、INMEMORY PRIORITY LOWで変更された表よりも優先されます。IM列ストアに十分な領域がない場合、Oracle Databaseは領域が使用可能になるまで追加オブジェクトを移入しません。

    • オブジェクトに対する変更がIM列ストアで記録されるまで、ALTER TABLEまたはALTER MATERIALIZED VIEW文からの返答を待機します

セグメントがIM列ストアに移入された後、データベースでそれが除去されるのは、そのセグメントが削除または移動されるか、NO INMEMORY属性で更新されるときのみです。セグメントは手動またはADOポリシーによって除去できます。

例6-1 IM列ストアへのオブジェクトの移入

この例を完了する前に、IM列ストアをデータベースに対して有効にする必要があります。

  1. データベースに管理者としてログインしてから、次のようにcustomers表を問い合せます。

    SELECT cust_id, cust_last_name, cust_first_name 
    FROM   sh.customers 
    WHERE  cust_city = 'Hyderabad' 
    AND    cust_income_level LIKE 'C%' 
    AND    cust_year_of_birth > 1960;
  2. 問合せの実行計画を表示します。

    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));
    SQL_ID  frgk9dbaftmm9, child number 0
    -------------------------------------
    SELECT cust_id, cust_last_name, cust_first_name FROM   sh.customers
    WHERE  cust_city = 'Hyderabad' AND    cust_income_level LIKE 'C%' AND
     cust_year_of_birth > 1960
    
    Plan hash value: 2008213504
    
    -------------------------------------------------------------------------------
    | Id| Operation         | Name      |Starts|E-Rows|A-Rows|   A-Time   |Buffers|
    -------------------------------------------------------------------------------
    |  0| SELECT STATEMENT  |           |     1|      |    6 |00:00:00.01 |   1523|
    |* 1|  TABLE ACCESS FULL| CUSTOMERS |     1|    6 |    6 |00:00:00.01 |   1523|
    -------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter(("CUST_CITY"='Hyderabad' AND "CUST_YEAR_OF_BIRTH">1960 AND
                  "CUST_INCOME_LEVEL" LIKE 'C%'))
    
  3. sh.customers表をIM列ストアへの移入のために有効にします。

    ALTER TABLE sh.customers INMEMORY;

    上の文では、デフォルトの優先順位であるNONEが使用されます。優先順位なしでオブジェクトを移入するには、全体スキャンが必要となります。

  4. sh.customers表からのデータがIM列ストアに移入されているかどうかを判断するには、次の問合せを実行します(出力例が含まれています)。

    SELECT SEGMENT_NAME, POPULATE_STATUS 
    FROM   V$IM_SEGMENTS 
    WHERE  SEGMENT_NAME = 'CUSTOMERS';
    
    no rows selected
    

    この場合、sh.customers表はまだスキャンされていないため、IM列ストアに移入されているセグメントはありません。

  5. ステップ1と同じ文を使用してsh.customersを問い合せます。

    SELECT cust_id, cust_last_name, cust_first_name 
    FROM   sh.customers 
    WHERE  cust_city = 'Hyderabad' 
    AND    cust_income_level LIKE 'C%' 
    AND    cust_year_of_birth > 1960;
    
  6. カーソルの問合せでは、データベースで全体スキャンを実行しIM列ストアにアクセスしたことが示されます。

    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(FORMAT=>'+ALLSTATS'));
    SQL_ID  frgk9dbaftmm9, child number 0
    -------------------------------------
    SELECT cust_id, cust_last_name, cust_first_name FROM   sh.customers
    WHERE  cust_city = 'Hyderabad' AND    cust_income_level LIKE 'C%' AND
     cust_year_of_birth > 1960
    
    Plan hash value: 2008213504
    
    ---------------------------------------------------------------------------------
    | Id| Operation           | Name            |Starts|E-Rows|A-Rows|A-Time|Buffers|
    ---------------------------------------------------------------------------------
    |  0| SELECT STATEMENT           |           |    1|     | 6 |00:00:00.02| 1523 |
    |* 1|  TABLE ACCESS INMEMORY FULL| CUSTOMERS |    1|    6| 6 |00:00:00.02| 1523 |
    ---------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - inmemory(("CUST_CITY"='Hyderabad' AND "CUST_YEAR_OF_BIRTH">1960 AND
                  "CUST_INCOME_LEVEL" LIKE 'C%'))
           filter(("CUST_CITY"='Hyderabad' AND "CUST_YEAR_OF_BIRTH">1960 AND
                  "CUST_INCOME_LEVEL" LIKE 'C%'))
    
  7. V$IM_SEGMENTSを再度問い合せます(出力例が含まれています)。

    COL SEGMENT_NAME FORMAT a20
    
    SELECT SEGMENT_NAME, POPULATE_STATUS 
    FROM   V$IM_SEGMENTS 
    WHERE  SEGMENT_NAME = 'CUSTOMERS';
    
    SEGMENT_NAME         POPULATE_STATUS
    -------------------- ---------------
    CUSTOMERS            COMPLETED

    POPULATE_STATUS内の値COMPLETEDは、表がIM列ストアに移入されていることを意味します。

  8. DBA_FEATURE_USAGE_STATISTICSビューでは、データベースでIM列ストアを使用して結果を取得したことを確認します。
    COL NAME FORMAT a25
    SELECT ul.NAME, ul.DETECTED_USAGES 
    FROM   DBA_FEATURE_USAGE_STATISTICS ul 
    WHERE  ul.VERSION= (SELECT MAX(u2.VERSION) 
                        FROM   DBA_FEATURE_USAGE_STATISTICS u2 
                        WHERE  u2.NAME = ul.NAME 
                        AND    ul.NAME LIKE '%Column Store%');
    
    NAME                      DETECTED_USAGES
    ------------------------- ---------------
    In-Memory Column Store    1
    

関連項目:

インメモリー・オブジェクトの移入の優先度オプション

INMEMORY PRIORITY句について学習するには、『Oracle Database SQL言語リファレンス』を参照

6.1.1.2 バックグラウンド・プロセスによるIMCUの移入方法

移入中、データベースは、行形式でディスクからデータを読み取り、列を作成するために行をピボットし、インメモリー圧縮ユニット(IMCU)にデータを圧縮します。

ワーカー・プロセス(Wnnn)は、IM列ストアにデータを移入します。各ワーカー・プロセスは、オブジェクトのデータベース・ブロックのサブセットで動作します。移入は、データを同時に圧縮して列形式に変換する、ストリーミング・メカニズムです。

INMEMORY_MAX_POPULATE_SERVERS初期化パラメータにより、IM列ストアの移入に使用するワーカー・プロセスの最大数を指定します。デフォルト設定は、CPU_COUNTの2分の1です。このパラメータは環境に適した値に設定します。ワーカー・プロセスの数を増加すると移入は高速化しますが、より多くのCPUリソースが使用されます。ワーカー・プロセスの数を削減すると、移入が低速化し、これによりCPUオーバーヘッドは低減します。

ノート:

INMEMORY_MAX_POPULATE_SERVERS0に設定されている場合、移入は無効化されます。

関連項目:

INMEMORY_MAX_POPULATE_SERVERS初期化パラメータの詳細は、『Oracle Databaseリファレンス』を参照してください。

6.1.2 手動インメモリー移入のユーザー・インタフェース

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

6.1.2.1 SELECTを使用した移入

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

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

SELECT COUNT(*) FROM object

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

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

関連項目:

6.1.2.2 DBMS_INMEMORY.POPULATEを使用した移入

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

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

BEGIN
  DBMS_INMEMORY.POPULATE( schema_name => 'SH', table_name => 'CUSTOMERS');
END;
/
6.1.2.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を返します。

表6-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

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

関連項目:

6.1.2.4 DBMS_INMEMORY.REPOPULATEを使用した移入

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

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

関連項目:

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

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

前提

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

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

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

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

ノート:

テキスト列ベースの問合せは、IMEU (インメモリー式単位)の移入が終了した後にのみ実行する必要があります。IMEUの移入が進行中に実行される問合せの実行は、通常よりもはるかに遅くなります。

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列ストアに移入されました。

関連項目:

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

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

6.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.

6.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

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

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

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

この例では、データベースに様々な優先順位設定のあるインメモリー表が数多く含まれています。目標は、制限付きデータベース・セッションですべてのインメモリー表に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;

6.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表が移入されたことを示しています

関連項目:

6.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');

関連項目: