7 結合グループによる結合の最適化

結合グループは、効果的に結合できる1つ以上の列をリストするユーザー作成ディクショナリです。

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

7.1 インメモリー結合について

結合は、データ・ウェアハウジング・ワークロードの不可欠な一部です。結合される表がメモリーに格納されている場合、IM列ストアにより、結合のパフォーマンスが向上します。

スキャンおよび結合処理が高速化されるため、ブルーム・フィルタを使用する複雑な複数表結合および単純な結合には、IM列ストアが役立ちます。データ・ウェアハウジング環境では、最も頻繁に使用される結合には、1つのファクト表と1つ以上のディメンション表が関与しています。

次の結合は、表がIM列ストアに移入される場合に、より高速に実行されます。

  • ブルーム・フィルタを使用できる結合

  • 複数の小規模なディメンション表の、1つのファクト表への結合

  • 主キーと外部キーの関係がある2つの表の間の結合

7.2 結合グループについて

IM列ストアが有効になっている場合、データベースでは、結合グループを使用して、IM列ストアに移入された表の結合を最適化できます。

結合グループは、一連の表が頻繁に結合される列のセットです。列セットには、1つ以上の列が含まれ、最大255の列が含まれます。表セットには、1つ以上の内部表が含まれます。外部表はサポートされていません。

結合グループ内の列は、同じ表内または異なる表内にある可能性があります。たとえば、salestimestime_id列で頻繁に結合される場合は、(times(time_id), sales(time_id))の結合グループを作成できます。employees表がemployee_id列でそれ自体に結合されることが多い場合、結合グループは(employees(employee_id))である可能性があります。

ノート:

同じ列が複数の結合グループのメンバーになることはできません。

結合グループを作成すると、データベースにより、その結合グループで参照されている表の現在のインメモリー・コンテンツが無効になります。後続の再移入により、データベースで、共通ディクショナリによる表のIMCUの再エンコードが引き起こされます。このため、最初に結合グループを作成し、その後、表に移入することをお薦めします。

CREATE INMEMORY JOIN GROUP文を使用して結合グループを作成します。結合グループに列を追加するか、結合グループから列を削除するには、ALTER INMEMORY JOIN GROUP文を使用します。DROP INMEMORY JOIN GROUP文を使用して結合グループを削除します。

ノート:

Oracle Active Data Guardでは、スタンバイ・データベースで結合グループ定義が無視されます。スタンバイ・データベースでは、共通ディクショナリは使用されず、結合グループが存在しないかのように問合せが実行されます。

例7-1 結合グループの作成

この例では、hr.employees表内およびhr.departments表内のdepartment_idを含む、deptid_jgという名前の結合グループを作成します。

CREATE INMEMORY JOIN GROUP deptid_jg (hr.employees(department_id),hr.departments(department_id));

7.3 結合グループの目的

特定の問合せでは、結合グループにより、列値の解凍およびハッシュについてパフォーマンスのオーバーヘッドがなくなります。

結合グループを使用しないときは、オプティマイザでハッシュ結合を使用するがブルーム・フィルタを使用できないか、ブルーム・フィルタで行が効率的にフィルタされない場合に、データベースで、IMCUを解凍し、コストのかかるハッシュ結合を使用する必要があります。問題を示すため、スター・スキーマにsalesファクト表およびvehiclesディメンション表があると仮定します。次の問合せでは、これらの表が結合されますが、出力はフィルタされません。これは、データベースでブルーム・フィルタを使用できないことを意味します。

SELECT v.year, v.name, s.sales_price
FROM   vehicles v, sales s
WHERE  v.name = s.name;

次の図に、データベースによる2つのデータ・セットの結合方法を示します。

図7-1 結合グループなしのハッシュ結合

図7-1の説明が続きます
「図7-1 結合グループなしのハッシュ結合」の説明

データベースは、次のようにハッシュ結合を実行します。

  1. vehicles表をスキャンし、述語を満たす行(このケースでは、フィルタが存在しないため、すべての行が述語を満たします)を解凍し、行をハッシュ結合に送信します。

  2. 解凍した行に基づいてPGAでハッシュ表を作成します

  3. sales表をスキャンし、フィルタを適用します(この場合、問合せはフィルタを指定しません)

  4. IMCUから一致する行を処理して、その行を結合に送信します

    調査側(この例では、sales表)の行セットがハッシュ結合で利用できる場合は、表スキャンによって送信される行セットは圧縮された形式になります。構築側から一致する行を検索するためにローカル・ディクショナリまたは結合グループが利用されるかどうかに応じて、ハッシュ結合で行が解凍されるか、未圧縮のままにされます。

  5. 結合列(この場合、乗物名)を使用してハッシュ表を調べます

結合グループがv.name列およびs.name列に存在する場合、データベースは前述のステップをより効率的に実行します(解凍とフィルタリングのオーバーヘッドがなくなります)。結合グループの利点は次のとおりです。

  • データベースは、圧縮されたデータに対して機能します。

  • データベースは、調査行とハッシュされた行の結合キーの比較が必要になる結合キーのハッシングとハッシュ表の調査を回避します。

    結合グループが存在する場合、データベースは結合列値ごとのコードを共通ディクショナリに格納します。データベースは、ディクショナリのコードを使用して結合グループの配列を作成します。すべての配列要素は、ハッシュ領域(通常は、PGAメモリー)に格納されている構築側の行をポイントしています。調査時に、各調査行は結合キーに関連付けられたコードを保持しています。データベースは、このコードを使用して配列を検索し、配列要素にポインタが存在しているかどうかを調べます。ポインタが存在する場合は一致があり、それ以外の場合は一致がありません。

  • ディクショナリ・コードは稠密および固定長であるため、領域が効率的に使用されます。

  • 結合グループによる問合せの最適化は、ブルーム・フィルタを使用できないときに可能な場合があります。

7.4 結合グループの仕組み

結合グループでは、データベースによって、同じ共通ディクショナリを使用して結合グループ内のすべての列が圧縮されます。

この項では、次の項目について説明します。

7.4.1 結合グループでどのように共通ディクショナリが使用されるか

共通ディクショナリは、表レベルの、インスタンス固有の一連のディクショナリ・コードです。

データベースでは、基になる列で結合グループが定義されている場合に、IM列ストア内に共通ディクショナリが自動的に作成されます。共通ディクショナリにより、複数の結合列で同じディクショナリ・コードを共有できるようになります。

共通ディクショナリには、次のような利点があります。

  • 共通ディクショナリからのコードでローカル・ディクショナリ内の値をエンコードします。それにより、圧縮が提供され、IMCUのキャッシュ効率が向上します

  • 結合でディクショナリ・コードを使用して、ハッシュ結合中に使用されるデータ構造を構成および調査できます

  • オプティマイザにより、カーディナリティ、列値の分布などの統計を取得できます

次の図は、sales.name列とvehicles.name列で作成された結合グループに対応する、共通ディクショナリを示しています。

図7-2 結合グループのための共通ディクショナリ

図7-2の説明が続きます
「図7-2 結合グループのための共通ディクショナリ」の説明

データベースで共通ディクショナリが使用される場合、各CUのローカル・ディクショナリには、元の値(AUDIBMWCADILLACFORDなど)は格納されません。かわりに、ローカル・ディクショナリには、共通ディクショナリに格納されている値への参照が格納されます。たとえば、ローカル・ディクショナリではAudiに値101BMWには220を格納できます。共通ディクショナリでは、Audi0BMW1を格納できます。ローカル・ディクショナリの101 (AUDI)は、共通ディクショナリの0 (AUDI)へのポインタです。

7.4.2 結合グループでどのようにスキャンが最適化されるか

主要な最適化は、列値ではなく共通ディクショナリ・コードでの結合であり、それによって、結合にハッシュ表を使用しないようにします。

結合グループを使用してvehiclessalesname列で結合する、次のような問合せについて考察します。

SELECT v.year, v.name, s.sales_price
FROM   vehicles v, sales s
WHERE  v.name = s.name
AND    v.name IN ('Audi', 'BMW', 'Porsche', 'VW');

次の図では、結合グループで作成された共通ディクショナリがどのように結合に役立つかを示します。

図7-3 結合グループありのハッシュ結合

図7-3の説明が続きます
「図7-3 結合グループありのハッシュ結合」の説明

前述の図に示されているように、データベースは次のように圧縮されたデータのハッシュ結合を実行します。

  1. vehicles表をスキャンし、0 (Audi)、1 (BMW)、2 (Cadillac)などのディクショナリ・コード(元の列値ではない)をハッシュ結合に送信します。

  2. PGA内で非重複共通ディクショナリ・コードの配列を構築します。

  3. sales表をスキャンし、フィルタを適用します(このケースでは、ドイツ車のみのフィルタとなります)

  4. 一致する行を、圧縮された形式で結合に送信します。

  5. ハッシュ表のプロービングではなく、配列内の対応する値を探します。それにより、結合キー列上のハッシュ関数を計算する必要がなくなります。

この例では、vehicles表には7行のみがあります。vehicles.name列には、次のような値があります。

Audi
BMW
Cadillac
Ford
Porsche
Tesla
VW

共通ディクショナリにより、ディクショナリ・コードが各非重複値に割り当てられます。概念的には、共通ディクショナリは、次のようになります。

Audi     0
BMW      1
Cadillac 2
Ford     3
Porsche  4
Tesla    5
VW       6

データベースで、vehicles.nameがスキャンされます。最初のIMCU内の最初のディクショナリ・コードから始まり、最後のIMCU内の最後のコードで終わります。フィルタ(ドイツ車のみ)に適合するすべての行については1、フィルタに適合しないすべての行については0が格納されます。概念上、配列は次のようになります。

array[0]: 1
array[1]: 1
array[2]: 0
array[3]: 0
array[4]: 1
array[5]: 0
array[6]: 1

データベースでは、次に、salesファクト表がスキャンされます。この例を単純化するために、sales表には6行のみがあると仮定します。データベースでは、次のように行がスキャンされます(値ごとの共通ディクショナリ・コードを括弧で囲んで示します)。

Cadillac (2)
Cadillac (2)
BMW      (1)
Ford     (3)
Audi     (0)
Tesla    (5)

データベースでは、次に、vehicles.name配列内を進み、一致を探します。行が一致すると、データベースにより、一致する行がその関連する共通ディクショナリ・コードとともに送信され、対応する列値がvehicles.nameおよびsales.name IMCUから取得されます。

2  -> array[2] is 0, so no join
2  -> array[2] is 0, so no join
1  -> array[1] is 1, so join
3  -> array[3] is 0, so no join
0  -> array[0] is 1, so join
5  -> array[5] is 0, so no join

7.5 ハッシュ結合で共通ディクショナリ・エンコーディングを使用する場合

通常、結合グループ内の列を結合することでパフォーマンスが向上します。

結合グループの作成時に、次の処理がデータベースによって実行されます。

  • 結合キー列に対応するディクショナリ値のハッシュがキャッシュされます

  • 結合キー列に対応するNUMBERデータのバイナリ表現がキャッシュされます

  • 同じ共通ディクショナリで列がエンコードされます

結合グループ内の列の結合では、最初の2つの最適化が常に使用されるためパフォーマンスが向上します。たとえば、オプティマイザがハッシュ結合を選択すると、問合せはブルーム・フィルタの調査にハッシュ値を使用するようになります。問合せでIM集計結合が使用される場合、問合せはキー・ベクターへの索引付けにキャッシュされた2進数を使用します。

ハッシュ結合には、ディクショナリ・エンコーディングが使用されることも使用されないこともあります。ハッシュ結合の少なくとも1つの列にディクショナリ・エンコーディングが存在する場合、問合せでは次の方法でエンコーディングを活用できます。

  • 結合グループ対応のハッシュ結合

    実行時に、ハッシュ結合の両方の列が共通ディクショナリ・エンコーディング・データを保持します。実行計画は、ハッシュ結合の両側が関与する分散のないパラレル・ハッシュ結合計画か、シリアル・ハッシュ結合計画のどちらかを必ず示します。

  • エンコーディング対応のハッシュ結合

    実行時に、ハッシュ結合内の1つのファクト表列がディクショナリ・エンコーディング・データを保持します。実行計画は、ハッシュ結合の右側からの分散のないパラレル・ハッシュ結合か、シリアル・ハッシュ結合計画のどちらかを必ず示します。共通ディクショナリの圧縮率が良好な場合や、パラレル・ハッシュ結合計画では結合グループ対応のハッシュ結合を活用できない場合(並列ブロードキャストなしの計画など)、問合せでは共通ディクショナリにエンコーディング対応ハッシュ結合を使用することもできます。

SQL監視レポートでは、ディクショナリの使用がColumnar Encodings ObservedフィールドとColumnar Encodings Leveragedフィールドで示されます。この統計は累積されます。パラレル・ハッシュ結合の場合、このフィールドには、行ソースの実行に関連するすべてのスレーブ・プロセスから収集した統計が集約されます。IMCU内のローカル・ディクショナリの観点では、この統計には、右側の子行ソースで観測されたエンコーディングIDの数と、結合で利用されたエンコーディングの数が示されます。単一プロセスのハッシュ結合が共通ディクショナリを利用する場合、Columnar Encodings Leveragedには、結合で利用されたエンコーディングの数が示されます。

次の表に、Columnar Encodings ObservedColumnar Encodings Leveragedに示される可能性のある値と、その組合せが意味する内容を示します。

表7-1 SQLモニター・レポートでの結合グループの使用状況

観測された列形式エンコーディング 利用された列形式エンコーディング エンコーディング対応ハッシュ結合の使用 結合グループ対応ハッシュ結合の使用

存在しない

存在しない

なし

なし

正の値

存在しない

なし

なし

正の値

正の値

あり

なし

存在しない

正の値

なし

はい

たとえば、Columnar Encodings Leveragedフィールドに4が示されていているときに(並列度が4であると仮定)、Columnar Encodings Observedフィールドが存在していない場合、問合せはハッシュ結合に結合グループを利用したことを意味します。Columnar Encodings Observedフィールドが4のときに、Columnar Encodings Leveragedフィールドが存在しない場合、ディクショナリ・エンコーディングが存在していても、問合せでは使用されなかったことを意味します。

様々な要因によって、問合せでエンコーディング対応ハッシュ結合が使用されなくなることがあります。こうした要因には次のものがあります。

  • 共通ディクショナリの圧縮率が最適でない。

  • 共通ディクショナリなしで表スキャンから渡された行セットが多すぎることが問合せで観測された。

  • 構築側の行の長さが長すぎる。

  • 構築側の行がPGAメモリーに収まりきらない。

  • 構築側に重複した結合キーがある。

7.6 結合グループの作成

CREATE INMEMORY JOIN GROUP文を使用して結合グループを定義します。

結合グループの候補は、結合述語で頻繁にペアにされる列です。代表的な例に、ファクト表とディメンション表を結合する列、または表をそれ自体に結合する列などがあります。

CREATE INMEMORY JOIN GROUP文は、結合グループをただちに定義します。これは、そのメタデータがデータ・ディクショナリに表示されることを意味します。データベースでは、共通ディクショナリはすぐには構成されません。正確に述べると、データベースでは、次回、結合グループ内で参照されている表が、IM列ストアに移入されるか再移入されるときに共通ディクショナリが構築されます。

ガイドライン

結合グループを作成、変更または削除すると、通常は、その結合グループ内で参照されている、基にあるすべての表が無効になります。そのため、表を最初に移入する前に結合グループを作成することをお薦めします。

結合グループを作成するには:

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

  2. 次の形式の文を使用して、結合グループを作成します。

    CREATE INMEMORY JOIN GROUP join_group_name ( table1(col1), table2(col2) );

    たとえば、次の文は、sales_products_jgという結合グループを作成します。

    CREATE INMEMORY JOIN GROUP sales_products_jg (sales(prod_id), products(prod_id));
  3. オプションで、データ・ディクショナリを問い合せて、結合グループの定義を表示します(出力例も示します)。

    COL JOINGROUP_NAME FORMAT a18
    COL TABLE_NAME FORMAT a8
    COL COLUMN_NAME FORMAT a7
    
    SELECT JOINGROUP_NAME, TABLE_NAME, COLUMN_NAME, GD_ADDRESS 
    FROM   DBA_JOINGROUPS;
    
    JOINGROUP_NAME     TABLE_NA COLUMN_ GD_ADDRESS
    ------------------ -------- ------- ----------------
    SALES_PRODUCTS_JG  SALES    PROD_ID 00000000A142AE50
    SALES_PRODUCTS_JG  PRODUCTS PROD_ID 00000000A142AE50
  4. 結合グループ内で参照されている表を移入します。または、現在移入されている場合は、それらを再移入します。

例7-2 結合グループの使用による問合せの最適化

この例では、データベースにSYSTEMとしてログインしてから、まだIM列ストアに移入されていないsalesおよびproductsprod_id列で結合グループを作成します。

CREATE INMEMORY JOIN GROUP 
  sh.sales_products_jg (sh.sales(prod_id), sh.products(prod_id));

IM列ストアへの移入のためにsh.sales表およびsh.products表を有効にします。

ALTER TABLE sh.sales INMEMORY;
ALTER TABLE sh.products INMEMORY;

次の問合せでは、それらの表がまだIM列ストアに移入されていないことが示されます(出力例が含まれています)。

COL OWNER FORMAT a3
COL NAME FORMAT a10
COL STATUS FORMAT a20

SELECT OWNER, SEGMENT_NAME NAME,
       POPULATE_STATUS STATUS
FROM   V$IM_SEGMENTS;

no rows selected

両方の表を問い合せて、それらをIM列ストアに移入します。

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

次の問合せでは、それらの表が現在はIM列ストアに移入されていることが示されます(出力例が含まれています)。

COL OWNER FORMAT a3
COL NAME FORMAT a10
COL PARTITION FORMAT a13
COL STATUS FORMAT a20

SELECT OWNER, SEGMENT_NAME NAME, PARTITION_NAME PARTITION,
       POPULATE_STATUS STATUS, BYTES_NOT_POPULATED
FROM   V$IM_SEGMENTS;

OWN NAME       PARTITION     STATUS               BYTES_NOT_POPULATED
--- ---------- ------------- -------------------- -------------------
SH  SALES      SALES_Q3_1998 COMPLETED            0
SH  SALES      SALES_Q4_2001 COMPLETED            0
SH  SALES      SALES_Q4_1999 COMPLETED            0
SH  PRODUCTS                 COMPLETED            0
SH  SALES      SALES_Q1_2001 COMPLETED            0
SH  SALES      SALES_Q1_1999 COMPLETED            0
SH  SALES      SALES_Q2_2000 COMPLETED            0
SH  SALES      SALES_Q2_1998 COMPLETED            0
SH  SALES      SALES_Q3_2001 COMPLETED            0
SH  SALES      SALES_Q3_1999 COMPLETED            0
SH  SALES      SALES_Q4_2000 COMPLETED            0
SH  SALES      SALES_Q4_1998 COMPLETED            0
SH  SALES      SALES_Q1_2000 COMPLETED            0
SH  SALES      SALES_Q1_1998 COMPLETED            0
SH  SALES      SALES_Q2_2001 COMPLETED            0
SH  SALES      SALES_Q2_1999 COMPLETED            0
SH  SALES      SALES_Q3_2000 COMPLETED            0

DBA_JOINGROUPSを問い合せ、結合グループに関する情報を取得します(出力例が含まれています)。

COL JOINGROUP_NAME FORMAT a18
COL TABLE_NAME FORMAT a8
COL COLUMN_NAME FORMAT a7

SELECT JOINGROUP_NAME, TABLE_NAME, COLUMN_NAME, GD_ADDRESS 
FROM   DBA_JOINGROUPS;

JOINGROUP_NAME     TABLE_NA COLUMN_ GD_ADDRESS
------------------ -------- ------- ----------------
SALES_PRODUCTS_JG  SALES    PROD_ID 00000000A142AE50
SALES_PRODUCTS_JG  PRODUCTS PROD_ID 00000000A142AE50

上の出力では、結合グループsales_products_jgが同じ共通ディクショナリ・アドレスで結合されていることが示されています。

関連項目:

7.7 結合グループの使用の監視

問合せで結合グループが使用されているかどうかを判断するには、グラフィカルなSQL監視レポート(推奨)を使用することも、DBMS_SQLTUNE.REPORT_SQL_MONITOR_XMLファンクションを使用するSQL問合せを使用することもできます。

ハッシュ結合で共通ディクショナリ・エンコーディングが使用される場合では、SQL監視の出力を解釈する方法について説明しています。

前提条件

結合グループを監視するには、次の前提条件を満たしている必要があります。

  • 結合グループが存在する必要があります。

  • 結合グループによって参照される列が、結合グループの作成に移入されている必要があります。

  • 結合グループを使用可能な結合問合せを実行する必要があります。

結合グループの使用を監視するには:

  1. 必要な権限があるユーザーとしてデータベースにログインします。

  2. 次のようにして、SQL IDを格納するSQL*Plus変数を作成します。

    VAR b_sqlid VARCHAR2(13)
  3. 結合グループ内の列で結合する問合せを実行します。

  4. 次のどちらかの方法を使用します。

    • グラフィカルなSQL監視レポート

      SQL監視レポートはEnterprise Managerで使用できます。SQL*Plusでは、次のようにDBMS_SQL_MONITOR.REPORT_SQL_MONITORを使用すると、SQL監視レポートを生成できます。

      SET TRIMSPOOL ON
      SET TRIM ON
      SET PAGES 0
      SET LINESIZE 1000
      SET LONG 1000000
      SET LONGCHUNKSIZE 1000000
      SPOOL /tmp/long_sql.htm
      SELECT DBMS_SQL_MONITOR.REPORT_SQL_MONITOR(
               sql_id       => :b_sqlid, 
               report_level => 'ALL', 
               TYPE         => 'active') 
      FROM   DUAL;
      SPOOL OFF

      ブラウザでレポートにアクセスし、ハッシュ結合の双眼鏡アイコンをクリックして、結合グループの統計を表示します。

    • コマンドラインでの問合せ

      問合せで、DBMS_SQLTUNE.REPORT_SQL_MONITOR_XMLファンクションを使用します。次に例を示します。

      SELECT
        encoding_hj.rowsource_id row_source_id,
          CASE
            WHEN encoding_hj.encodings_observed IS NULL     
            AND encoding_hj.encodings_leveraged IS NOT NULL 
            THEN
              'join group was leveraged on ' || encoding_hj.encodings_leveraged || ' processes'
            ELSE
              'join group was NOT leveraged'
          END columnar_encoding_usage_info
      FROM
        (SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR_XML(session_id=>-1,sql_id=>:b_sqlid).
                EXTRACT(q'#//operation[@name='HASH JOIN' and @parent_id]#') xmldata
         FROM   DUAL) hj_operation_data,
        XMLTABLE('/operation'
          PASSING hj_operation_data.xmldata
          COLUMNS
           "ROWSOURCE_ID"        NUMBER PATH '@id',
           "ENCODINGS_LEVERAGED" NUMBER PATH 'rwsstats/stat[@id="9"]',
           "ENCODINGS_OBSERVED"  NUMBER PATH 'rwsstats/stat[@id="10"]') encoding_hj;

次の各項では、結合グループの使用情報を取得するための2つの方法について説明します。

7.7.1 SQLモニター・レポートを使用した結合グループの監視: 例

グラフィカルなSQL監視レポートを使用して、問合せで結合グループが利用されたかどうかを判断できるようにします。

この例では、sh.products表およびsh.sales表のprod_id列で結合グループを作成してから、これらの表をこの列で結合します。shアカウントに管理権限を付与します。

例7-3 SQLモニター・レポートを使用した結合グループの監視

  1. SQL*Plusで、ユーザーshとしてデータベースにログインします。

  2. SQL IDを格納するためのSQL*Plus変数を次のように作成します。

    VAR b_sqlid VARCHAR2(13)
  3. 次のようにINMEMORY属性をsh.products表およびsh.sales表に適用します。

    ALTER TABLE sales NO INMEMORY;
    ALTER TABLE products NO INMEMORY;
    
    ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY;
    ALTER TABLE products INMEMORY MEMCOMPRESS FOR QUERY;
    
  4. prod_idで結合グループを作成します。

    CREATE INMEMORY JOIN GROUP jgrp_products_sales (products(prod_id), sales(prod_id)); 
  5. それらの表をスキャンしてIM列ストアに移入します。

    SELECT /*+ FULL(s) */ COUNT(*) FROM sales s;
    SELECT /*+ FULL(p) */ COUNT(*) FROM products p;
  6. prod_id列で結合する問合せを実行してから、商品売上を集計します。

    SELECT /*+ USE_HASH(sales) LEADING(products sales) MONITOR */ products.prod_id, 
           products.prod_category_id, SUM(sales.amount_sold) 
    FROM   products, sales 
    WHERE  products.prod_id = sales.prod_id 
    GROUP BY products.prod_category_id, products.prod_id;
  7. DBMS_SQLTUNE.REPORT_SQL_MONITORを使用して、HTMLベースのSQL監視レポートを生成します。

    たとえば、次に示す内容のSQLスクリプトを作成して、SQL*Plusで実行します。

    SET TRIMSPOOL ON
    SET TRIM ON
    SET PAGES 0
    SET LINESIZE 1000
    SET LONG 1000000
    SET LONGCHUNKSIZE 1000000
    SPOOL /tmp/jg_report.htm
    SELECT DBMS_SQL_MONITOR.REPORT_SQL_MONITOR(
             sql_id       => :b_sqlid, 
             report_level => 'ALL', 
             TYPE         => 'active') 
    FROM   DUAL;
    SPOOL OFF
  8. ブラウザで、HTMLレポートを開きます。

    次のレポート例は、結合の実行計画を示しています。ハッシュ結合の双眼鏡アイコンで、追加の統計が示されるウィンドウを開きます。

    図7-4 「監視されたSQL実行の詳細」ページ

    図7-4の説明が続きます
    「図7-4 「監視されたSQL実行の詳細」ページ」の説明
  9. 双眼鏡アイコンをクリックして、結合グループの統計を表示するウィンドウを開きます。

    次に、統計が表示されたウィンドウの例を示します。

    Columnar Encodings Leveragedが正の値であり、Columnar Encodings Observedが存在していないことから、結合グループが利用されたことがわかります。

  10. 必要に応じて、この例の後でクリーン・アップを実行します。

    DROP INMEMORY JOIN GROUP jgrp_products_sales;
    ALTER TABLE sales NO INMEMORY;
    ALTER TABLE products NO INMEMORY;

関連項目:

7.7.2 コマンドラインからの結合グループの監視: 例

コマンドライン・ツールを使用して、問合せで結合グループが利用されたかどうかを判断できるようにします。

この例では、sh.products表およびsh.sales表のprod_id列で結合グループを作成してから、これらの表をこの列で結合します。shアカウントに管理権限を付与します。

例7-4 コマンドラインからの結合グループの監視

  1. shとしてデータベースにログインします。

  2. SQL IDを格納するためのSQL*Plus変数を次のように作成します。

    VAR b_sqlid VARCHAR2(13)
  3. 次のようにINMEMORY属性をsh.products表およびsh.sales表に適用します。

    ALTER TABLE sales NO INMEMORY;
    ALTER TABLE products NO INMEMORY;
    
    ALTER TABLE sales INMEMORY MEMCOMPRESS FOR QUERY;
    ALTER TABLE products INMEMORY MEMCOMPRESS FOR QUERY;
    
  4. prod_idで結合グループを作成します。

    CREATE INMEMORY JOIN GROUP jgrp_products_sales (products(prod_id), sales(prod_id)); 
  5. それらの表をスキャンしてIM列ストアに移入します。

    SELECT /*+ FULL(s) */ COUNT(*) FROM sales s;
    SELECT /*+ FULL(p) */ COUNT(*) FROM products p;
  6. prod_id列で結合する問合せを実行してから、商品売上を集計します。

    SELECT /*+ USE_HASH(sales) LEADING(products sales) MONITOR */ products.prod_id, 
           products.prod_category_id, SUM(sales.amount_sold) 
    FROM   products, sales 
    WHERE  products.prod_id = sales.prod_id 
    GROUP BY products.prod_category_id, products.prod_id;
  7. 前述の集計問合せのSQL IDを取得します。

    BEGIN
      SELECT PREV_SQL_ID 
        INTO :b_sqlid
      FROM   V$SESSION 
      WHERE  SID=USERENV('SID');
    END;
    
  8. DBMS_SQLTUNE.REPORT_SQL_MONITOR_XMLを使用して、データベースで結合グループが使用されたかどうかを判断します。

    たとえば、次の問合せを実行します。

    COL row_source_id FORMAT 999
    COL columnar_encoding_usage_info FORMAT A40
    
    SELECT
      encoding_hj.rowsource_id row_source_id,
        CASE
          WHEN encoding_hj.encodings_observed IS NULL     
          AND encoding_hj.encodings_leveraged IS NOT NULL 
          THEN
            'join group was leveraged on ' || encoding_hj.encodings_leveraged || ' processes'
          ELSE
            'join group was NOT leveraged'
        END columnar_encoding_usage_info
    FROM
      (SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR_XML(session_id=>-1,sql_id=>:b_sqlid).
              EXTRACT(q'#//operation[@name='HASH JOIN' and @parent_id]#') xmldata
       FROM   DUAL
      ) hj_operation_data,
      XMLTABLE('/operation'
        PASSING hj_operation_data.xmldata
        COLUMNS
         "ROWSOURCE_ID"       NUMBER PATH '@id',
         "ENCODINGS_LEVERAGED" NUMBER PATH 'rwsstats/stat[@id="9"]',
         "ENCODINGS_OBSERVED"  NUMBER PATH 'rwsstats/stat[@id="10"]'
         ) encoding_hj;

    次の出力例は、問合せで結合グループが利用されたことを示しています。

    ROW_SOURCE_ID COLUMNAR_ENCODING_USAGE_INFO
    ------------- ----------------------------------------
                2 join group was leveraged on 1 processes
  9. 必要に応じて、例の後にクリーン・アップを実行します。

    DROP INMEMORY JOIN GROUP jgrp_products_sales;
    ALTER TABLE sales NO INMEMORY;
    ALTER TABLE products NO INMEMORY;

関連項目: