日本語PDF

2 インメモリー列ストアのアーキテクチャ

インメモリー列ストア(IM列ストア)では、高速スキャン用に最適化された列形式を使用して、表およびパーティションがメモリーに格納されます。Oracle Databaseでは、高機能なアーキテクチャを使用して、列形式と行形式で同時にデータを管理します。

2.1 デュアルフォーマット: 列と行

IM列ストアを有効にした場合は、SGAにより、インメモリー領域とデータベース・バッファ・キャッシュという別々の場所でデータが管理されます。

IM列ストアでは、データが列形式でエンコードされます。各列は独立した構造となります。それらの列は隣接して格納され、分析問合せのために最適化されます。データベース・バッファ・キャッシュでは、IM列ストアにも移入されるオブジェクトを変更できます。ただし、バッファ・キャッシュでは、データが従来の行形式で格納されます。データ・ブロックでは、行はトランザクションのために最適化され、隣接して格納されます。

次の図では、行ベースのストレージと列ストレージとの違いを示します。

図2-1 列および行ベースのストレージ

図2-1の説明が続きます
「図2-1 列および行ベースのストレージ」の説明

2.1.1 インメモリー領域内の列データ

インメモリー領域は、IM列ストアが含まれる、オプションのSGAコンポーネントです。

2.1.1.1 インメモリー領域のサイズ

インメモリー領域は、INMEMORY_SIZE初期化パラメータによって制御されます。デフォルトでは、インメモリー領域のサイズは0であり、これは、IM列ストアが無効になっていることを意味します。

IM列ストアを有効にするには、インメモリー領域を少なくとも100 MBに設定します。サイズは、V$SGAで示されます。

インメモリー領域とSGA_TARGET

インメモリー領域は、SGA_TARGET初期化パラメータの設定から差し引かれます。たとえば、SGA_TARGETを10 GBに設定し、INMEMORY_SIZEを4 GBに設定した場合は、SGA_TARGET設定の40%がインメモリー領域に割り当てられます。次の図に、この関係を示します。

図2-2 INMEMORY_SIZEとSGA_TARGET

図2-2の説明が続きます
「図2-2 INMEMORY_SIZEとSGA_TARGET」の説明

バッファ・キャッシュおよび共有プールなど、SGAのその他のコンポーネントと異なり、インメモリー領域のサイズは、自動メモリー管理によって制御されません。データベースでは、バッファ・キャッシュまたは共有プールでさらにメモリーが必要な場合に自動的にインメモリー領域が縮小されることや、インメモリー領域が領域不足の場合に拡大されることはありません。

インメモリー領域の動的サイズ変更

Oracle Database 12cリリース2 (12.2)以降は、ALTER SYSTEM文を使用することで、INMEMORY_SIZEを動的に拡大できます。次の条件が満たされた場合に、データベースにより、増加したメモリーが割り当てられます。

  • SGAに空きメモリーがある。

  • INMEMORY_SIZEの新しいサイズが、現在の設定よりも128 MB以上大きい。

    ノート:

    ALTER SYSTEMを使用してINMEMORY_SIZEを縮小することはできません。

V$INMEMORY_AREAおよびV$SGAビューには、即座にその変更内容が反映されます。

マルチテナント環境のインメモリー領域

CDBでは、IM列ストアのサイズはCDBルートのINMEMORY_SIZEパラメータによって設定されます。デフォルトでは、IM列ストアはPDB間で共有されます。その結果、使用可能なメモリーを消費することによって、PDBが他のPDBを枯渇させる場合があります。

PDB内では、ALTER SYSTEM SET INMEMORY_SIZEを使用してメモリー使用量を制限することができます。たとえばCDBレベルでは、INMEMORY_SIZE20Gに設定し、PDBを次のように構成します。

  • hrpdbで、INMEMORY_SIZE0に設定します

  • salespdbで、INMEMORY_SIZE10Gに設定します

  • oepdbで、INMEMORY_SIZE11Gに設定します

前述の例では、CDBレベルのINMEMORY_SIZE20Gのみであっても、PDBレベルのINMEMORY_SIZE設定は21Gに追加されます。オーバーサブスクリプションは、PDBが停止または切断されている場合に、IM列ストアの貴重な領域が消費されないようにします。

関連項目:

2.1.1.2 インメモリー領域内のメモリー・プール

インメモリー領域は、列データおよびメタデータのために複数のサブプールに分割されます。

インメモリー領域は、さらに次のサブプールに分割されます。

  • 列データ・プール

    このサブプールには、列データを含むIMCUが格納されます。例2-1で示すように、V$INMEMORY_AREA.POOL列では、このサブプールは1MB POOLとして識別されます。

  • メタデータ・プール

    このサブプールには、IM列ストア内に存在するオブジェクトについてのメタデータが格納されます。例2-1で示すように、V$INMEMORY_AREA.POOL列では、このサブプールは64KB POOLとして識別されます。

図2-3 インメモリー領域内のサブプール

図2-3の説明が続きます
「図2-3 インメモリー領域内のサブプール」の説明

データベースでは、2つのサブプールの相対的なサイズは内部ヒューリスティックを使用して決まります。データベースでは、インメモリー領域内のほとんどの領域が列データ・プール(1 MBプール)に割り当てられます。

ノート:

Oracle Databaseにより、サブプール・サイズが自動的に決定されます。領域割当てを変更することはできません。

例2-1 V$INMEMORY_AREAビュー

この例では、V$INMEMORY_AREAビューを問い合せ、各サブプール内のメモリーの空き容量を測定します(出力例が含まれています)。

COL POOL FORMAT a9
COL POPULATE_STATUS FORMAT a15
SSELECT POOL, TRUNC(ALLOC_BYTES/(1024*1024*1024),2) "ALLOC_GB",
        TRUNC(USED_BYTES/(1024*1024*1024),2) "USED_GB",
        POPULATE_STATUS
FROM    V$INMEMORY_AREA;

POOL      ALLOC_GB   USED_GB    POPULATE_STATUS
--------- ---------- ---------- ---------------
1MB POOL  7.99       0          DONE
64KB POOL 1.98       0          DONE

インメモリー領域の現在のサイズはV$SGAで表示可能です。

SELECT NAME, VALUE/(1024*1024*1024) "SIZE_IN_GB"
FROM   V$SGA 
WHERE  NAME LIKE '%Mem%';

NAME                 SIZE_IN_GB
-------------------- ----------
In-Memory Area       10

この例では、サブプールに割り当てられているメモリーは9.97 GBであるのに対して、インメモリー領域のサイズは10 GBです。データベースでは、内部管理構造のためにメモリーのごく一部が使用されます。

関連項目:

V$INMEMORY_AREAについて学習するには、『Oracle Databaseリファレンス』を参照してください。

2.1.2 データベース・バッファ・キャッシュ内の行データ

データベース・バッファ・キャッシュでは、IM列ストアが有効でも無効でも同じようにデータ・ブロックが格納および処理されます。バッファI/Oおよびバッファ・プールは、同じ機能を果たします。

IM列ストアによって、データは従来の行形式(バッファ・キャッシュ)および列形式の両方でSGAに同時に移入されます。データベースは透過的にOLTP問合せ(主キー参照など)をバッファ・キャッシュに送信し、分析問合せおよびレポート問合せをIM列ストアに送信します。データをフェッチする場合は、Oracle Databaseで、同じ問合せ内で両方のメモリー領域からデータを読み取ることもできます。

ノート:

実行計画では、操作TABLE ACCESS IN MEMORY FULLは、IM列ストア内で一部またはすべてのデータがアクセスされることを示します。

デュアル形式アーキテクチャではメモリー要件は倍増しません。バッファ・キャッシュは、データベースのサイズよりもはるかに小さいサイズで稼働するように最適化されます。

次の図に、IM列ストアのサンプルを示します。データベースで、sh.sales表がディスクに従来の行形式で格納されます。SGAはデータをIM列ストアに列形式で格納し、データベース・バッファ・キャッシュに行形式で格納します。

永続的なヒープ構成表のどのディスク上データ形式もみな、IM列ストアでサポートされます。列形式は、データ・ファイルまたはバッファ・キャッシュに格納されているデータの形式には影響せず、データのUNDO、オンラインREDOロギングにも影響しません。

データベースでは、バッファ・キャッシュ、オンラインREDOログおよびUNDO表領域を更新することで、IM列ストアが有効になっているかどうかにかかわらず、DML変更が同じ方法で処理されます。ただし、データベースは内部メカニズムを使用して変更を追跡し、IM列ストアと残りのデータベースとの一貫性を保ちます。たとえば、sales表がIM列ストアに移入されており、アプリケーションによってsales内の行が更新される場合、データベースでは、自動的にIM列ストア内のsales表のコピーに関してトランザクションの一貫性が保たれます。IM列ストアにアクセスする問合せは常に、バッファ・キャッシュにアクセスする問合せと同じ結果を返します。

関連項目:

データベース・バッファ・キャッシュについてさらに学習するには、Oracle Database概要を参照してください。

2.2 インメモリー記憶域単位

IM列ストアでは、データとメタデータの両方が、従来のOracleデータ・ブロックではなく、最適化された記憶域単位で管理されます。

Oracle Databaseでは、記憶域単位はインメモリー領域内で保持されます。次の図では、インメモリー領域の概要、およびそれとやり取りするデータベース・プロセスを示します。残りの章では、様々なメモリー・コンポーネントを説明します。

図2-5 IM列ストア: メモリーおよびプロセスのアーキテクチャ

図2-5の説明が続きます
「図2-5 IM列ストア: メモリーおよびプロセスのアーキテクチャ」の説明

2.2.1 インメモリー圧縮ユニット(IMCU)

インメモリー圧縮単位(IMCU)は、圧縮された、読取り専用の記憶域単位であり、1つ以上の列のためにデータを含みます。

IMCUは、表領域エクステントに似ています。IMCUには、一連の列圧縮単位(CU)、およびIM記憶域索引などのメタデータを含むヘッダーという、2つの部分があります。

2.2.1.1 IMCUとスキーマ・オブジェクト

IM列ストアでは、一連のIMCUに、単一のオブジェクト(表、パーティション、マテリアライズド・ビュー)のデータが格納されます。IMCUには、1つのオブジェクトについてのみ列データが格納されます。

2.2.1.1.1 IMCUとINMEMORY列

INMEMORYとして指定されたオブジェクトの場合は、INMEMORY句でリストされたすべての列がすべてのIMCUに含まれます。

たとえば、sh.sales表に7つの列があるとします。次のDDL文では、その表がINMEMORYとして指定されます。これは、salesのためのすべてのIMCUに、これら7列の列データが含まれることを意味します。

ALTER TABLE sh.sales INMEMORY MEMCOMPRESS FOR QUERY LOW;

INMEMORYオブジェクトにINMEMORY列がありません

INMEMORY表のすべてではなく一部の列のみにINMEMORY属性を指定できます。たとえば、sh.customers表に23個の列があるとします。次のDDL文では、sh.customersの15列にNO INMEMORY属性があることを指定します。これは、表の他の8列にINMEMORY属性があることを意味します。

ALTER TABLE sh.customers INMEMORY 
  MEMCOMPRESS FOR QUERY LOW
  NO INMEMORY ( cust_gender, cust_year_of_birth, cust_marital_status,
                cust_postal_code, cust_city, cust_state_province,
                cust_main_phone_number, cust_income_level, cust_credit_limit,
                cust_email, cust_total, cust_total_id, cust_eff_from,
                cust_eff_to, cust_valid );

次の問合せでは、sh.customersの列の圧縮レベルが表示され、どの列がNO INMEMORYかが示されます。

SET LINESIZE 200
COL TABLE_NAME FORMAT a25
COL SEG_COL_ID FORMAT 999
COL COLUMN_NAME FORMAT a25
COL INMEMORY_COMPRESSION FORMAT a11
SELECT SEGMENT_COLUMN_ID AS "SEG_COL_ID", COLUMN_NAME, INMEMORY_COMPRESSION 
FROM   V$IM_COLUMN_LEVEL WHERE TABLE_NAME = 'CUSTOMERS'
ORDER BY SEG_COL_ID;

SEG_COL_ID COLUMN_NAME               INMEMORY_CO
---------- ------------------------- -----------
         1 CUST_ID                   DEFAULT
         2 CUST_FIRST_NAME           DEFAULT
         3 CUST_LAST_NAME            DEFAULT
         4 CUST_GENDER               NO INMEMORY
         5 CUST_YEAR_OF_BIRTH        NO INMEMORY
         6 CUST_MARITAL_STATUS       NO INMEMORY
         7 CUST_STREET_ADDRESS       DEFAULT
         8 CUST_POSTAL_CODE          NO INMEMORY
         9 CUST_CITY                 NO INMEMORY
        10 CUST_CITY_ID              DEFAULT
        11 CUST_STATE_PROVINCE       NO INMEMORY
        12 CUST_STATE_PROVINCE_ID    DEFAULT
        13 COUNTRY_ID                DEFAULT
        14 CUST_MAIN_PHONE_NUMBER    NO INMEMORY
        15 CUST_INCOME_LEVEL         NO INMEMORY
        16 CUST_CREDIT_LIMIT         NO INMEMORY
        17 CUST_EMAIL                NO INMEMORY
        18 CUST_TOTAL                NO INMEMORY
        19 CUST_TOTAL_ID             NO INMEMORY
        20 CUST_SRC_ID               DEFAULT
        21 CUST_EFF_FROM             NO INMEMORY
        22 CUST_EFF_TO               NO INMEMORY
        23 CUST_VALID                NO INMEMORY

次の図では、customersproductsおよびsalesという、IM列ストアに移入されたshスキーマからの3つの表を示します。この例では、各表で、異なる数の列にINMEMORYが指定されています。各表のIMCUには、INMEMORY列のデータのみが含まれています。

NO INMEMORY列を参照する問合せ

問合せがNO INMEMORY列を参照する場合、表スキャンによってIM列ストア内のIMCUではなく、行ストアからデータを取得します。行ストアのアクセスは、問合せで参照される他の列すべてにINMEMORY列が移入されている場合でも発生します。

たとえば、IM列ストアにcustomers表が移入されるとします。cust_idおよびcust_last_name列にはINMEMORYが指定されていますが、cust_postal_code列はNO INMEMORYと指定されています。次の問合せを発行します。

SELECT cust_id, cust_last_name, cust_postal_code 
FROM   customers 
WHERE  cust_id < 5001
ORDER BY cust_id;

この場合、cust_postal_codeが問合せで参照されている唯一のNO INMEMORY列であっても、IM列ストアではなく行ストアにアクセスします。次の問合せでは、述語にcust_postal_codeがあってSELECTリストがなく、行ストアにもアクセスする必要があります。

SELECT cust_id, cust_last_name 
FROM   customers 
WHERE  cust_postal_code = 77501
ORDER BY cust_id;

関連項目:

2.2.1.1.2 インメモリー圧縮

IM列ストアでは、記憶域の削減よりはむしろアクセス速度の面で最適化された特別な圧縮形式が使用されます。列形式によって問合せを、圧縮された列に対して直接実行できます。

圧縮により、スキャン操作およびフィルタ操作で処理するデータ量を非常に少なくできるため、問合せパフォーマンスが向上します。Oracle Databaseでは結果セットに必要な場合のみ、データが圧縮解除されます。

IM列ストアで適用される圧縮は、ハイブリッド列圧縮と密接に関係しています。どちらの技術も列ベクターを処理します。主な違いは、IM列ストアの列ベクターがSIMDベクター処理の面で最適化されているのに対し、ハイブリッド列圧縮の列ベクターはディスク記憶域の面で最適化されている点です。

オブジェクトをIM列ストアに移入できるようにする場合は、INMEMORY句で、FOR DMLFOR QUERY (LOWまたはHIGH)、FOR CAPACITY (LOWまたはHIGH)またはNONEの圧縮タイプを指定します。

関連項目:

2.2.1.1.3 IMCUと行

各IMCUには、表セグメント内の行のサブセットのすべての列値(nullを含む)が含まれます。行のサブセットは、グラニュルと呼ばれます。

指定されたセグメントのすべてのIMCUには、ほぼ同数の行が含まれます。Oracle Databaseでは、データ型、データ形式および圧縮タイプに応じて、グラニュルのサイズが自動的に判断されます。圧縮レベルが高いと、IMCU内の行数が多くなります。

IMCUとデータベース・ブロックのセットの間には1対多マッピングが存在します。例2-2で示すように、各IMCUには、異なるブロック・セットの列の値が格納されます。

IMCU内の列はソートされません。Oracle Databaseでは、それらはディスクから読み取られた順に移入されます。

IMCU内の行の数により、IMCUに使用される容量が決定されます。対象行数によって、1 MBプール内で使用可能な隣接する1 MBのエクステントの量を超えてIMCUが拡大する場合、IMCUにより、残りの列CUを保持するための追加のエクステント(ピース)が作成されます。IMCUでは、必ず1 MBずつ領域が割り当てられます。

例2-2 IMCUと行のサブセット

この単純化された例では、customers表のcust_idcust_first_namecust_last_nameおよびcust_genderという4列のみにINMEMORY属性があります。5行のみがその表に存在し、2つのデータ・ブロックに格納されています。概念的には、最初のデータ・ブロックにはその行が次のように格納されています。

82,Madeline,Li,F;37004,Abel,Embrey,M;1714,Hardy,Gentle,M

2つ目のデータ・ブロックには、行が次のように格納されています。

100439,Uma,Campbell,F;3047,Lucia,Downey,F

IMCU 1には最初のデータ・ブロックのデータが格納されると仮定します。このケースでは、このデータ・ブロック・ストア内のそれら3行のcust_id列値は、CU内で次のように垂直に格納されます。

82
37004
1714

IMCU 2には、2つ目のデータ・ブロックからデータが格納されます。これら2行のcust_id列値は、CU内で次のように格納されます。

100439
3047

cust_id値はデータ・ブロック内の各行の最初の値であるため、cust_id列は、IMCU内で先頭の位置にあります。列は必ず同じ位置を使用します。そのため、Oracle Databaseでは、セグメントのIMCUを読み取ることで、行を再構成できます。

2.2.1.2 列圧縮単位(CU)

列圧縮単位(CU)は、IMCU内の単一列のための隣接する記憶域です。すべてのIMCUに1つ以上のCUがあります。

2.2.1.2.1 CUの構造

CUは、本体とヘッダーに分けられます。

すべてのCUの本体には、IMCUに含まれている行の範囲で列値が格納されます。ヘッダーには、CU本体に格納されている値に関してメタデータが含まれます。たとえば、CU内の最小値および最大値です。また、ローカル・ディクショナリが含まれる場合もあります。これは、その列内の非重複値のソート済リスト、およびそれらに対応するディクショナリ・コードです。

次の図では、sales表のprod_idcust_idtime_idおよびchannel_idという4つのCUがあるIMCUを示します。各CUには、IMCUに含まれている行の範囲で列値が格納されます。

CUには、ROWIDの順序で値が格納されます。このため、データベースは、行を元どおりにまとめることで問合せに答えることができます。たとえば、アプリケーションによって次のような問合せが発行されるとします。

SELECT cust_id, time_id, channel_id
FROM   sales
WHERE  prod_id =5;

データベースでは、まず、prod_id列に値が5のエントリがあるかどうかが調べられます。データベースで、prod_id列内の位置2に5が見つかったとします。データベースは、次に、この行の対応するcust_idtime_idおよびchannel_idを見つける必要があります。CUでは行順でデータが格納されるため、データベースは、対応するcust_idtime_idおよびchannel_id値をそれらの列内の位置2で見つけることができます。したがって、この問合せに答えるには、データベースは、cust_idtime_idおよびchannel_id列内の位置2から値を抽出し、行を元どおりにまとめ、それをエンド・ユーザーに返す必要があります。

2.2.1.2.2 ローカル・ディクショナリ

CUでは、ローカル・ディクショナリに、非重複値のリスト、およびそれらの対応するディクショナリ・コードが含まれます。

ローカル・ディクショナリには、列に含まれている記号が格納されます。次の図に、CUによるvehicles表のname列の格納方法を示します。

図2-8 ローカル・ディクショナリ

図2-8の説明が続きます
「図2-8 ローカル・ディクショナリ」の説明

上の図では、CUには7行のみが含まれています。CadillacAudiなど、このCU内のすべての非重複値には、Cadillacの場合は2Audiの場合は0というように、異なるディクショナリ・コードが割り当てられます。CUには、元の値ではなくディクショナリ・コードが格納されます。

ノート:

データベースで結合グループのために共通ディクショナリが使用される場合、ローカル・ディクショナリには、記号ではなく共通ディクショナリへの参照が含まれます。たとえば、ローカル・ディクショナリには、vehicles.name列の値AudiBWMおよびCadillacが格納されるのではなく、101220および66などのディクショナリ・コードが格納されます。

CUヘッダーには、列の最小値および最大値が含まれます。この例では、最小値はAudiで、最大値はCadillacです。ローカル・ディクショナリには、AudiBMWおよびCadillacという非重複値のリストが格納されます。それらの対応するディクショナリ・コード(01および2)は暗黙的です。各IMCU内のCUのローカル・ディクショナリは、他のIMCU内のローカル・ディクショナリから独立しています。

問合せによってAudi社の自動車でフィルタする場合、データベースでは、0のコードのみについて、このIMCUがスキャンされます。

2.2.1.3 インメモリー記憶域索引

すべてのIMCUヘッダーでは、そのCUのためのインメモリー記憶域索引(IM記憶域索引)が自動的に作成および管理されます。IM記憶域索引では、IMCU内のすべての列の最小値および最大値が格納されます。

たとえば、salesがIM列ストアに移入されるとします。この表のためのすべてのIMCUには、すべての列が含まれています。sales.prod_id列は、すべてのIMCU内の別個のCUに格納されます。IMCUヘッダーには、各prod_id CU (および他のすべてのCU)の最小値および最大値が含まれています。

不要なスキャンをなくすには、データベースで、SQLフィルタ述語に基づいてIMCUプルーニングを実行します。次の図のWHERE prod_id > 14 AND prod_id < 29例に示すように、データベースでは問合せの述語を満たすIMCUのみをスキャンします。

図2-9 列データの記憶域索引

図2-9の説明が続きます
「図2-9 列データの記憶域索引」の説明

2.2.2 スナップショット・メタデータ単位(SMU)

スナップショット・メタデータ単位(SMU)には、関連するIMCUのメタデータおよびトランザクション情報が含まれます。

2.2.2.1 IMCUとSMU

インメモリー領域の列プールには、IMCUおよびIMEUという実データが格納されます。インメモリー領域内のメタデータ・プールには、SMUが格納されます。

図2-10 IMCUとSMU

この図には、データ・プール内のIMCU、およびメタデータ・プール内のSMUを示します。

図2-10の説明が続きます
「図2-10 IMCUとSMU」の説明

すべてのIMCUは、別個のSMUにマップされます。したがって、列データ・プールに100個のIMCUが含まれる場合、メタデータ・プールには100個のSMUが含まれます。SMUには、関連付けられているIMCUについて、次のようないくつかのタイプのメタデータが格納されます。

  • オブジェクト番号

  • 列番号

  • 行のマッピング情報

2.2.2.2 トランザクション・ジャーナル

すべてのSMUには、トランザクション・ジャーナルが含まれます。データベースでは、トランザクション・ジャーナルを使用して、IMCUに関するトランザクションの一貫性が保たれます。

データベースでは、IM列ストアが有効になっていない場合と同様に、バッファ・キャッシュを使用してDMLが処理されます。たとえば、UPDATE文で、IMCU内の行を変更するとします。このケースでは、データベースにより、変更した行のROWIDがトランザクション・ジャーナルに追加され、それがDML文のSCNの時点で失効とマークされます。問合せで新しいバージョンの行にアクセスする必要がある場合は、データベースにより、データベース・バッファ・キャッシュからその行が取得されます。

図2-11 トランザクション・ジャーナル

図2-11の説明が続きます
「図2-11 トランザクション・ジャーナル」の説明

データベースでは、列、トランザクション・ジャーナルおよびバッファ・キャッシュの内容をマージすることで、読取り一貫性が実現されます。再移入中にIMCUがリフレッシュされた場合は、問合せで、IMCUから直接、最新の行にアクセスできます。

関連項目:

どのようにIM列ストアでトランザクションの一貫性が維持されるかの詳細は、IM列ストアの再移入の最適化を参照してください。

2.2.3 インメモリー式単位(IMEU)

インメモリー式単位(IMEU)は、マテリアライズされたインメモリー式(IM式)、およびユーザーが定義した仮想列のための記憶域コンテナです。

データベースではマテリアライズされた式が、IMCUの他の列と同様に取り扱われます。概念的には、IMEUは、その親IMCUの論理拡張です。IMCUに複数の列を含むことができるのと同様に、IMEUには複数の仮想列を含むことができます。

すべてのIMEUは1つのIMCUのみにマップされ、同じ行セットにマップされます。IMEUには、関連付けられているIMCU内に含まれたデータについて式結果が含まれます。IMCUが移入されると、関連付けられているIMEUも移入されます。

一般的なIM式には、1つ以上の列が含まれており、定数が使用されている場合もあります。また、表内の行と1対1でマップされています。たとえば、employees表のIMCUに、列weekly_salaryの行1から1000が含まれているとします。このIMCUに格納されている行について、IMEUで、自動検出されたIM式weekly_salary*52、およびweekly_salary*12として定義されているユーザー定義の仮想列quarterly_salaryが計算されます。IMCU内の3番目の行は、IMEU内の3番目の行にマップされます。

IMEUは、特定セグメントのIMCUの論理拡張です。デフォルトでは、IMEUは、基本セグメントから、DISTRIBUTEDUPLICATEなどのOracle Real Application Clusters (Oracle RAC)プロパティを含むINMEMORY句プロパティを継承します。IMEU内の記憶域に対して仮想列を有効または無効にすることを選択できます。様々な列に対して圧縮レベルを指定することもできます。

2.3 式統計ストア(ESS)

式統計ストア(ESS)は、式評価についての統計を格納するためにオプティマイザによって保持されるリポジトリです。ESSはSGAにあり、ディスクに保持されます。

IM列ストアが有効になっている場合、データベースでは、そのインメモリー式(IM式)機能のためにESSが利用されます。ただし、ESSは、IM列ストアから独立しています。ESSは、データベースの永続的コンポーネントであり、無効にはできません。

データベースでは、ESSを使用して、式がホット(頻繁にアクセスされている)かどうか、ひいてはIM式の候補が判断されます。問合せのハード解析の間には、ESSにより、SELECTリスト、WHERE句、GROUP BY句などに含まれているアクティブな式が探されます。

ESSにより、セグメントごとに次のような式統計が保持されます。

  • 実行頻度

  • 評価コスト

  • タイムスタンプ評価

オプティマイザにより、コストおよび評価された回数に基づいて、各式に重み付きのスコアが割り当てられます。値は、正確ではなく概算となります。アクティブな式ほど、高いスコアとなります。ESSでは、最も頻繁にアクセスされた式について内部リストが保持されます。

DBMS_INMEMORY_ADMINパッケージを使用して、IM式の挙動を制御します。たとえば、IME_CAPTURE_EXPRESSIONSプロシージャは、データベースに、データベース内の最もホットな式を特定して徐々に移入するよう求めます。IME_POPULATE_EXPRESSIONSプロシージャは、データベースに、すぐに式を移入するよう強制します。

ESS情報は、データ・ディクショナリに格納され、DBA_EXPRESSION_STATISTICSビューで公開されます。このビューでは、オプティマイザによってESSに収集されたメタデータが示されます。IM式は、SYS_IMEという文字列で接頭辞が付けられ、DBA_IM_EXPRESSIONSビューで、システム生成の仮想列として公開されます。

関連項目:

2.4 インメモリー・プロセスのアーキテクチャ

サーバー・プロセスは、問合せおよびDMLに応答して、列データをスキャンし、SMUメタデータを更新します。バックグラウンド・プロセスは、ディスクからIM列ストアに行データを移入します。

2.4.1 インメモリー・コーディネータ・プロセス(IMCO)

インメモリー・コーディネータ・プロセス(IMCO)では、IM列ストアのための多くのタスクが管理されます。その主要タスクは、列データのバックグラウンド移入および再移入の開始です。

移入はストリーミング・メカニズムであり、行データを列形式に変換してから、それを圧縮します。IMCOにより、NONE以外の任意の優先順位で、自動的にINMEMORYオブジェクトの移入が開始されます。優先順位がNONEのオブジェクトがアクセスされた場合は、IMCOにより、領域管理ワーカー・プロセス(Wnnn)のプロセスを使用してそれらが移入されます。

また、IMCOバックグラウンド・プロセスでは、IM列ストア・オブジェクトが失効しきい値に達したときに、それらのしきい値ベース再移入が開始されます。IMCOでは、失効エントリが存在するが失効しきい値に満たないIM列ストア内の任意のIMCUに対して、トリクル再移入を引き起こす場合があります。

トリクル再移入はバックグラウンドで自動的に行われます。ステップは次のとおりです。

  1. IMCOが起動します。

  2. IMCOでは、IMCUに失効エントリが存在するかどうかも含めて、移入タスクを実行する必要性の有無が判断されます。

  3. IMCOで失効エントリが見つかった場合、領域管理ワーカー・プロセスがトリガーされてこれらのエントリがIMCUで再移入されます。

  4. IMCOは2分間スリープしてから、ステップ1に戻ります。

関連項目:

2.4.2 領域管理ワーカー・プロセス(Wnnn)

領域管理ワーカー・プロセス(Wnnn)は、IMCOにかわってデータを移入または再移入します。

移入中に、Wnnnプロセスは、IMCU、SMUおよびIMEUを作成する役割を担います。IMEUの作成時は、ワーカー・プロセスにより、次のようなタスクが実行されます。

  • 移入のための仮想列を特定する

  • 仮想列値を作成する

  • 各行の値を計算し、データを列形式に変換し、それを圧縮する

  • オブジェクトを領域レイヤーに登録する

  • IMEUをそれらの対応するIMCUに関連付ける

ノート:

IMEUを作成する間も、親IMCUは、引き続きキューで使用可能です。

再移入中は、Wnnnプロセスにより、既存のIMCUおよびトランザクション・ジャーナルに基づいて、IMCUの新しいバージョンが作成され、古いバージョンは一時的に保持されます。このメカニズムは、ダブル・バッファリングと呼ばれます。

データベースは、IM列ストアの内外にIM式を迅速に移動できます。たとえば、IMCUがIMEUなしで作成された場合、データベースは、IMCUに再移入メカニズム全体を強制的に経験させることなく、後でIMEUを追加できます。

INMEMORY_MAX_POPULATE_SERVERS初期化パラメータは、移入のために開始できる、ワーカー・プロセスの最大数を制御します。INMEMORY_TRICKLE_REPOPULATE_PERCENT初期化パラメータは、ワーカー・プロセスがトリクル再移入を実行できる回数の最大パーセンテージを制御します。

2.4.3 In-Memory動的スキャン

In-Memory動的スキャン(IM動的スキャン)は、軽量スレッドを使用して、インメモリー表スキャンをパラレル化します。

2.4.3.1 IM動的スキャンの目的

追加のCPUが使用可能な場合、IM動的スキャンは、CPUにバインドされたインメモリー表スキャンを高速化します。

IM動的スキャンは、自動的にアイドル状態のCPUリソースを使用してIMCUを並行してスキャンし、CPU使用率を最大化します。CPUリソースが使用可能な場合、アプリケーションはより高速な分析問合せ結果を自動的に取得できます。スキャンは動的なため、既存のワークロードに影響を与えずに余分なCPU帯域幅を使用できます。

IM動的スキャンは、従来のOracleのパラレル実行よりも柔軟性がありますが、相互に排他的ではありません。動的スキャンは、プロセス内で複数の軽量スレッドの実行を使用します。通常、動的スキャンのパフォーマンス・オーバーヘッドは少なくなっています。

関連項目:

リソース・マネージャについてさらに学習するには、Oracle Database管理者ガイドを参照

2.4.3.2 IM動的スキャンの仕組み

IM動的スキャンは、IMCUを並行して読み取ることで最適なパフォーマンスを実現します。

2.4.3.2.1 軽量スレッドについて

軽量スレッドは、全表スキャンをパラレル化するために役立つ実行エンティティです。Oracleプロセスのメモリー・オーバーヘッドが増えないため「軽量」です。

ノート:

IM動的スキャンで使用される軽量スレッドは、マルチスレッドOracle Databaseモデルの通常スレッドと同じではありません。

軽量スレッドは、一連のIMCUのスキャンを調整する、表スキャンプロセスという親フォアグラウンドまたはPQプロセスのリソースを共有します。スレッドは独自の独立した実行フローを維持します。データベースは、スレッドの優先度付けと非同期実行によってスキャンをパラレル化できます。

対象となる問合せの場合、プロセスはスレッドのプールを割り当てます。リソース・マネージャは、データベース・ホストのCPU数およびシステムでの現在の負荷に基づいてプール内のスレッド数を自動的に決定します。アイドル時間が内部しきい値に達して、その時点でデータベースがスレッドを終了しないかぎり、スレッドのプールは後続の問合せのためにセッションで使用可能なままです。

スレッド間の通信は、プロセス内で排他的に発生します。このため、データベース・インスタンス・レベルで競合は発生しません。

関連項目:

マルチスレッドOracle Databaseモデルについて学習するには、Oracle Database概要を参照

2.4.3.2.2 データベースがIM動的スキャンを考慮する場合

軽量スレッドは、CPUリソース・プランが有効で(たとえば、RESOURCE_MANAGER_PLAN=DEFAULT_PLAN)、データベースのCPU使用率が低い場合に有効になります。

軽量スレッドが有効な場合、データベースは、現在IM列ストアに移入されているオブジェクトをアプリケーションが問い合せたときに、IM動的スキャンを考慮します。通常、シリアルまたはパラレル問合せは、次の特性を持つ場合にIM動的スキャンの候補となります。

  • 多数のIMCUまたは列にアクセスする

  • 表内のすべての行を消費する

  • CPUに負担がかかる

Oracle Database Resource Manager (リソース・マネージャ)は、INMEMORY_SIZE0より大きい場合に自動的に有効化されます。また、IM動的スキャンに必要です。リソース・マネージャは、軽量スレッドを使用するタイミングと方法を決定します。軽量スレッドは、未使用のリソースを利用しているため、データベース内で最も優先度の低い操作です。

ノート:

IM動的スキャンを実行するには、CPU_COUNT24以上である必要があります。
2.4.3.2.3 IM動的スキャンの仕組み

リソース・マネージャが軽量スレッドを割り当てて、IMCUのスキャンをパラレル化します。

問合せがIM動的スキャンによる利益を得られるとデータベースが判断した場合、通常は次のように進みます。

  1. 表スキャン・プロセスが、軽量スレッドのプールを生成します。

  2. 表スキャン・プロセスは、スキャンが必要なすべてのIMCU用に個別のタスクを作成した後、各タスクをタスク・キューに追加します。

  3. リソース・マネージャが、表スキャンに参加できるスレッド数を決定します。

  4. アクティブ・スレッドがタスク・キューからタスクを選択し、表スキャン・プロセスは完了したタスクの結果を消費します。

データベースの負荷に応じて、リソース・マネージャは問合せの実行中にアクティブな軽量スレッドの数を継続して調整します。 CPUリソースが使用できない場合、表スキャン・プロセスは軽量スレッドを使用せずにスキャンを実行します。

次の図は、sales表内の12個のIMCUのIM動的スキャンを示しています。

図2-12 IM動的スキャン

図2-12の説明が続きます
「図2-12 IM動的スキャン」の説明

前の図では、データベース・ホストに8つのCPUコアがあります。内部アルゴリズムに基づいて、リソース・マネージャは4つのスレッドを割り当てて表スキャン・プロセスを支援します。このシナリオでは、4つのCPUコアが他の同時データベース操作で使用するためにアイドル状態のままになります。

2.4.3.3 IM動的スキャンのインタフェース

IM動的スキャンは透過的です。これは、アプリケーションの変更を必要としないことを意味し、リソース・マネージャによって自動的に制御されます。

IM動的スキャンでは、リソース・マネージャが必要です。これは、INMEMORY_SIZE0より大きい場合に自動的に有効になります。特定のリソース・プランは必要ありません。

いくつかの新しいセッション統計が、IM動的スキャンの使用状況を追跡します。各スレッドは、トレース・データを別のトレース・ファイルに書き込みます。

実行計画は変更されていません。次の図に、実行計画のサンプルを示します。

SQL> SELECT MAX(l_quantity) largest_order FROM lineitem;

LARGEST_ORDER
-------------
           50

Elapsed: 00:00:03.41

Execution Plan
----------------------------------------------------------
Plan hash value: 1885658499
-------------------------------------------------------------------------------------------
|Id| Operation                   | Name     |Rows| Bytes |Cost(%CPU)| Time  |Pstart| Pstop|
-------------------------------------------------------------------------------------------
|0| SELECT STATEMENT             |          |    1 |    3| 116K  (4)| 00:00:05 |    |     |
|1|  SORT AGGREGATE              |          |    1 |    3|          |          |    |     |
|2|   PARTITION RANGE ALL        |          | 600M |1716M| 116K  (4)| 00:00:05 |  1 |  84 |
|3|    TABLE ACCESS INMEMORY FULL| LINEITEM | 600M |1716M| 116K  (4)| 00:00:05 |  1 |  84 |
-------------------------------------------------------------------------------------------

NAME                                              VALUE
-------------------------------------------------------
IM scan CUs memcompress for query low              1147
IM scan bytes in-memory                      5.1790E+10
IM scan bytes uncompressed                   7.6722E+10
IM scan CUs columns accessed                       1147
IM scan rows                                  600037902
IM scan rows projected                               29
IM scan (dynamic) rows                        600037902
IM scan (dynamic) multi-threaded scans                1
IM scan (dynamic) tasks processed by thread        1146

計画の特性を考えてみます。

  1. 実行計画は変更されていません。

    計画では、ステップ3でIM動的スキャンに言及していないので注意してください。ただし、SQLモニター・レポートの双眼鏡アイコンをクリックすると、「スレッドの動的スキャン・タスク」が表示されます。

  2. IM scan (dynamic) multi-threaded scansがゼロ以外の場合、データベースがIM動的スキャンを使用したことを意味します。

  3. IM scan CUs memcompress for query lowは、lineitem表に1147個のIMCUが存在することを示しています。

  4. IM scan (dynamic) tasks processed by threadは、並列処理されたIMCUの数を示しています。

    その数は1146で、IM scan CUs memcompress for query lowで示されている1147の合計数より少ない数です。データベースは、パラレル化なしで最初のIMCUを分析して、パラレル化に価値があるかどうかを判断しました。答えは「はい」であったため、データベースは残りの1146個のIMCUを並行してスキャンしました。

  5. IM scan (dynamic) rowsおよびIM scan rows are equalは、スレッドで問合せのすべての行が取得されたことを意味します。

関連項目:

2.5 CPUアーキテクチャ: SIMDベクター処理

IM列ストアに移入されるデータについては、データベースはSIMD (単一命令、複数データ)処理を使用します。

SIMDユニットは、データを複数の別々の命令で処理するのではなく、単一の命令で、ベクトルという1つの単位としてデータを処理できるようにするプロセッサです。たとえば、ループを使用して4つの追加操作を実行するのではなく、SIMDでは、4つの数値セットをベクトルにロードし1つの追加操作を実行できます。SIMD処理は、ベクトル化と呼ばれることもあります。

IM列ストアでは、CPUでベクター・レジスタにロードして評価できる、列エントリの数が最大化されます。列内の各エントリを1回に1つずつ評価するかわりに、データベースは単一のCPU命令で列値のセットを評価します。SIMDベクター処理により、データベースで、1秒当たり何十億もの行をスキャンできるようになります。

たとえば、promo_id値に9999を使用した、sales表内の注文の総数を確認する問合せをアプリケーションが発行します。sales表は、IM列ストア内に存在します。問合せでは、まず、次の図に示すようにsales.promo_id列のみがスキャンされます。

図2-13 SIMDベクター処理

図2-13の説明が続きます
「図2-13 SIMDベクター処理」の説明

CPUではデータが次のように評価されます。

  1. promo_id列の最初の8つの値(値の数はデータ型と圧縮モードによって異なる)がSIMDレジスタにロードされ、単一の命令で9999という値と比較されます。

  2. エントリが破棄されます。

  3. 別の8つの値がSIMDレジスタにロードされ、すべてのエントリが評価されるまでこのように続きます。

2.5.1 SIMDおよびOracle LOB

Oracleデータベース18cは、特定のLOB列に対するSQL演算子を含む問合せに対するSIMDベクター・サポートを提供します。

サポートの内容は、LOBの種類によって異なります。

  • インラインLOB

    IM列ストアは、IMCU内の4KB未満のLOBであるインラインLOBに対して連続した記憶域を提供します。列型記憶域により、データベース・バッファ・キャッシュからLOBデータをアセンブルするオーバーヘッドを排除することで、より高速な問合せ処理が可能です。

  • アウトラインLOB

    この場合、IM列ストアは40バイトのLOBロケータのみを格納します。アウトライン列は、列の最適化による利益を得られません。

前述のルールには、例外が1つあります。IMEUは、LOBデータ型として定義されたJSON列に対して最大32KBの連続した記憶域を割り当てることができます。IMEUは、これらの列をOSON形式で格納します。これにより、SIMD処理を使用してより高速な問合せのパフォーマンスを提供できます。

関連項目:

LOBについてさらに学習するには、Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイドを参照してください。

2.5.2 SIMDおよびOracle Numbers

QUERY LOWで表を圧縮する場合、NUMBER列は、ハードウェアでのネイティブ計算が有効になる最適化された形式を使用してエンコードされます。

SIMDベクター処理では、単純な集計、GROUP BY集計、算術演算を使用でき、大きいメリットがあります。パフォーマンスの向上は、集計が算術計算に費やす時間によって異なります。集計によっては、最大9倍までの効果があります。

2.5.3 SIMDおよびExadataスマート・フラッシュ・キャッシュ

ハイブリッド列圧縮形式でデータを格納する他、Exadataスマート・フラッシュキャッシュはデータを純粋な列形式で格納できます。

Exadata Smart ScanはSIMD述語をサポートします。利点は、インメモリーのパフォーマンスがDRAM記憶域から二次記憶域に及ぶことです。

デフォルトでは、Exadataスマート・フラッシュ・キャッシュは、レベルMEMCOMPRESS FOR CAPACITY LOWを使用してデータを圧縮します。圧縮レベルを変更するか、列形式を完全に無効にするには、ALTER TABLE ... NO CELLMEMORY文を使用します。