7 インメモリー集計による結合の最適化

Oracle Database 12cリリース1 (12.1.0.2)以降、インメモリー集計(IM集計)では、問合せにおいて、スキャン処理しながら集計できます。

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

7.1 IM集計について

IM集計では、集計に関与する問合せブロックが最適化され、1つの大きい表から複数の小さい表に結合されます。

KEY VECTORおよびVECTOR GROUP BY操作では、結合および集計のために効率的な配列が使用されます。オプティマイザにより、コストに基づくGROUP BY操作のためにVECTOR GROUP BYが選択されます。オプティマイザでは、GROUP BY ROLLUPGROUPING SETSまたはCUBE操作のためにVECTOR GROUP BY集計が選択されることはありません。

ノート:

IM集計は、ベクター集計およびVECTOR GROUP BY集計とも呼ばれます。

IM集計では、INMEMORY_SIZEがゼロ以外の値に設定される必要があります。ただし、IM集計では、参照される表がIM列ストアに移入されている必要はありません。

7.2 IM集計の目的

IM集計では、大きい表で実行される、行ごとの処理を高速化するために、小さい表が前処理されます。

一般的な分析問合せでは、ファクト表から集計し、それをディメンション表に結合します。このタイプの問合せは、大量のデータをスキャンし、オプションでフィルタ処理を行い、1列から40列までのGROUP BYを実行します。ファクト表での最初の集計で、ほとんどの行が処理されます。

Oracle Database 12cより前は、GROUP BY操作はHASHおよびSORTのみでした。VECTOR GROUP BYは、ディメンション表とファクト表との結合をフィルタに変換する、追加のコストベースの変換です。データベースでは、ファクト表のスキャン中にこのフィルタを適用できます。結合では、ブルーム・フィルタに似たキー・ベクターが使用され、集計では、VECTOR GROUP BYが使用されます。

ノート:

ベクター変換はIM列ストアから独立していますが、SIMDベクター処理によってそれらをインメモリー・データに非常に効率的に適用できます。

IM集計により、ベクトル結合およびGROUP BY操作を、大きな表のスキャンと同時に行うことができるようになります。したがって、これらの操作では、スキャンしながら集計されるため、表のスキャンおよび結合操作の完了を待つ必要はありません。IM集計では、CPU使用率、特にCPUキャッシュが最適化されます。

IM集計により、問合せのパフォーマンスを大幅に改善できます。データベースでは、動的にレポート概要を作成し、ファクト表のスキャン中にレポート詳細を入力できます。

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

関連項目:

7.2.1 IM集計が役立つ場合

IM集計により、比較的小さい表を比較的大きい表に結合してファクト表内のデータを集計する問合せのパフォーマンスが向上します。これは通常、スター・クエリーまたはスノーフレーク・クエリーで起こります。

行ストア表およびIM列ストア内の表の両方に、IM集計が役立ちます。

例7-1 VECTOR GROUP BY

customersディメンション表とsalesファクト表の結合を実行する、次のような問合せを想定します。

SELECT c.customer_id, s.quantity_sold, s.amount_sold 
FROM   customers c, sales s
WHERE  c.customer_id = s.customer_id 
AND    c.country_id = 'FR';

両方の表がIM列ストアに移入される場合、データベースでは、SIMDベクター処理を使用して、行セットをスキャンし、フィルタを適用できます。次の図では、ベクトル結合が問合せでどのように使用されるかを示します。オプティマイザにより、customers表の述語、c.country_id='FR'が、salesファクト表上のフィルタに変換されます。フィルタはcountry_id='FR'です。salesは列形式で格納されるため、問合せでは、結果を決定するために1列のスキャンしか必要になりません。

図7-1 インメモリー列ストアを使用したベクトル結合

図7-1の説明が続きます
「図7-1 インメモリー列ストアを使用したベクトル結合」の説明

7.2.2 IM集計が役立たない場合

IM集計は、十分なシステム・リソースが存在する場合に、特定のスター・クエリーに役立ちます。他の問合せには、ほとんどまたはまったく利益がない場合があります。

VECTOR GROUP BY集計が不利な状況

具体的に述べると、VECTOR GROUP BY集計は、次のシナリオにおいてはパフォーマンス向上に役立ちません。

  • 2つの非常に大きな表の間で結合が実行される。

    デフォルトでは、比較的小さい表が比較的大きい表に結合される場合のみ、オプティマイザでVECTOR GROUP BY変換が選択されます。

  • ディメンションに、20億以上の行が含まれる。

    ディメンションに20億以上の行が含まれる場合、VECTOR GROUP BY変換は使用されません。

  • システムに十分なメモリーがない。

    IM列ストアを使用するほとんどのデータベースには、IM集計が役立ちます。

7.3 インメモリー集計の仕組み

通常の分析問合せはファクト表から集計し、ファクト表を1つ以上のディメンションに結合します。

このタイプの問合せは、大量のデータをスキャンし、オプションでフィルタ処理を行い、1列から40列までのGROUP BYを実行します。オプティマイザは、キー・ベクター(個別の結合キー)のサイズや個別のグループ化キーの数などの考慮事項に基づいて、ベクター変換を使用するかどうかを決定します。ディメンション結合キーのカーディナリティが低い場合に、オプティマイザはこの変換を選択する傾向があります。

VECTOR GROUP BY集計では、大きな表で実行する行ごとの処理時間を短縮するために、小さな表の処理に前もって時間が割かれます。通常の分析問合せでは、次に示す処理ステージに行が分散されるため、この最適化が可能です。

  1. 表のフィルタ処理と行セットの生成

  2. 行セットの結合

  3. 行の集計

ステージ間の作業単位をデータ・フロー演算子(DFO)と呼びます。VECTOR GROUP BY集計では、ディメンションごとにDFOを使用して、キー・ベクター構造と一時表を作成します。ファクト表のメジャー列を集計する場合、データベースではこのキー・ベクターを使用して、ファクト結合キーをその稠密グループ化キーに変換します。遅延マテリアライズ・ステップは、稠密グループ化キーで一時表に結合します。

7.3.1 オプティマイザでIM集計が選択される場合

オプティマイザでは、キー・ベクター(つまり、非重複結合キー)のサイズ、非重複グループ化キーの数、およびその他の要因に基づいて、ベクター変換を使用するかどうかが決定されます。ディメンション結合キーのカーディナリティが低い場合に、オプティマイザはこの変換を選択する傾向があります。

Oracle Databaseは、次の条件が満たされた場合、VECTOR GROUP BY集計を使用してデータ集計を実行します。

  • 問合せまたは副問合せは、ファクト表からのデータを集計し、ファクト表を1つ以上のディメンションに結合します。

    これらのファクト表が結合のみを介してディメンションに接続されているという想定では、同じディメンションに結合された複数のファクト表もサポートされます。この場合、VECTOR GROUP BYはファクト表を別々に集計し、グループ化キー上で結果を結合します。

  • ディメンションとファクト表は、結合列を介してのみ互いに接続されます。

    特に、問合せには、複数のディメンションを通じて、またはディメンションとファクト表から、列を参照する述語が他にないようにする必要があります。問合せが2つ以上の表の間の結合を実行し、結果をファクトに結合する場合、VECTOR GROUP BY集計は、複数のディメンションを1つのディメンションとみなします。

ノート:

問合せブロックのヒントまたは表ヒントを使用して、問合せに対してVECTOR GROUP BY集計を使用するようにデータベースに指示できます。

VECTOR GROUP BY集計は、次の場合をサポートしていません。

  • 複数のディメンションの間、またはディメンション表とファクト表の間の半結合と逆結合

  • 複数のディメンションの間の等価結合

  • DISTINCT関数を使用して実行される集計

ノート:

ブルーム・フィルタおよびVECTOR GROUP BY集計は互いに矛盾します。そのため、問合せでブルーム・フィルタを使用して行セットを結合する場合は、この問合せの処理にVECTOR GROUP BY集計を適用できません。

関連項目:

SQL集計についてさらに学習するには、『Oracle Databaseデータ・ウェアハウス・ガイド』を参照

7.3.2 キー・ベクター

キー・ベクターは、稠密結合キーと稠密グループ化キー間をマップするデータ構造です。

稠密キーは、ネイティブ整数として格納され、値の範囲を持つ数値キーです。稠密結合キーは、結合列が特定のファクト表またはディメンションから取得されるすべての結合キーを表します。稠密グループ化キーは、グループ化列が特定のファクト表またはディメンションから取得されるすべてのグループ化キーを表します。キー・ベクターは、高速参照を可能にします。

例7-2 キー・ベクター

hr.locations表に、次のようなcountry_idの値があるとします(結果のうち冒頭の一部のみを示しています)。

SQL> SELECT country_id FROM locations;
 
CO
--
IT
IT
JP
JP
US
US
US
US
CA
CA
CN

複合分析問合せは、フィルタWHERE country_id='US'locations表に適用します。このフィルタのキー・ベクターは、次の1次元配列のようになります。

0
0
0
0
1
1
1
1
0
0
0

前の配列では、1country_id='US'の稠密グループ化キーです。0の値は、このフィルタに一致しないlocationsの行を示します。問合せでフィルタWHERE country_id IN ('US','JP')を使用する場合、配列は次のようになります。ここで、2JPの稠密グループ化キー、1USの稠密グループ化キーです。

0
0
2
2
1
1
1
1
0
0
0

7.3.3 インメモリー集計の2つのフェーズ

一般に、VECTOR GROUP BY集計では、各ディメンションが順々に処理されてから、ファクト表が処理されます。

インメモリー集計を実行する場合、データベースは次のように処理を行います。

  1. 各ディメンションを次の順序で処理します。

    1. 一意の稠密グループ化キーを検索します。

    2. キー・ベクターを作成します。

    3. 一時表(CURSOR DURATION MEMORY)を作成します。

    次の図では、DFO 0のディメンション表のスキャンで開始し、一時表の作成で終了する、このフェーズのステップを示します。最も単純な形式のパラレルGROUP BYまたは結合処理では、データベースは自身のDFO内で各結合またはGROUP BYを処理します。

    図7-2 インメモリー集計のフェーズ1

    図7-2の説明が続きます
    「図7-2 インメモリー集計のフェーズ1」の説明
  2. ファクト表を処理します。

    1. 前のフェーズで作成したキー・ベクターを使用して、すべての結合と集計を処理します。

    2. 結果を各一時表に再び結合します。

    図7-3に、2つのディメンションがあるファクト表の結合のフェーズ2を示します。DFO 0では、データベースはファクト表の全スキャンを実行し、各ディメンションのキー・ベクターを使用して不一致の行をフィルタで除外します。DFO 2は、DFO 0の結果をDFO 1と結合します。DFO 4は、DFO 2の結果をDFO 3と結合します。

    図7-3 インメモリー集計のフェーズ2

    図7-3の説明が続きます
    「図7-3 インメモリー集計のフェーズ2」の説明

7.3.4 IM集計: シナリオ

この項では、VECTOR GROUP BY集計の仕組みの概念的な例を示します。

ノート:

シナリオに使用しているスキーマ表はサンプルではなく、表示されている実行計画も実際のものではありません。

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

7.3.4.1 スター・スキーマのサンプル分析問合せ

このシナリオのサンプル・スター・スキーマには、sales_onlineファクト表と、2つのディメンション表geographyおよびproductsが含まれます。

geographyの各行は、geog_id列で一意に識別されます。productsの各行は、prod_id列で一意に識別されます。sales_onlineの各行は、geog_id列、prod_id列および販売量で一意に識別されます。

表7-1 geography表のサンプル行

geog_id

USA

WA

seattle

2

USA

WA

spokane

3

USA

CA

SF

7

USA

CA

LA

8

表7-2 products表のサンプル行

製造者 カテゴリ サブカテゴリ prod_id

Acme

スポーツ

バイク

4

Acme

スポーツ

ボール

3

Acme

電気

電球

1

Acme

電気

スイッチ

8

表7-3 sales_online表のサンプル行

prod_id geog_id

8

1

100

9

1

150

8

2

100

4

3

110

2

30

130

6

20

400

3

1

100

1

7

120

3

8

130

4

3

200

仕事上でマネージャに、「各サブカテゴリのAcme製品が、ワシントンでオンライン販売された数と、カリフォルニアで販売された数はいくつだったか」と聞かれたとします。この質問に答えるには、sales_onlineファクト表の分析問合せでproductsおよびgeographyディメンション表を次のように結合します。

SELECT p.category, p.subcategory, g.country, g.state, SUM(s.amount)
FROM   sales_online s, products p, geography g
WHERE  s.geog_id = g.geog_id 
AND    s.prod_id = p.prod_id
AND    g.state IN ('WA','CA')
AND    p.manuf = 'ACME'
GROUP BY category, subcategory, country, state
7.3.4.2 ステップ1: geographyディメンションのキー・ベクターと一時表の作成

この問合せのVECTOR GROUP BY集計の最初のフェーズでは、データベースはワシントンまたはカリフォルニア州の市について、各市/州の組合せに対する稠密グループ化キーを作成します。

表7-6では、1USA,WAグループ化キーで、2USA,CAグループ化キーです。

表7-4 geographyの稠密グループ化キー

geog_id dense_gr_key_geog

USA

WA

seattle

2

1

USA

WA

spokane

3

1

USA

CA

SF

7

2

USA

CA

LA

8

2

geography表のキー・ベクターは、表7-5の最後の列で表される配列のようになります。値は、geography稠密グループ化キーです。したがって、キー・ベクターは、sales_onlineのどの行がgeography.stateフィルタ基準(CAまたはWAの州の販売)を満たし、各行がどの国/州グループ(USA、WAグループまたはUSA、CAグループ)に属するかを示します。

表7-5 オンライン販売

prod_id geog_id geographyのキー・ベクター

8

1

100

0

9

1

150

0

8

2

100

1

4

3

110

1

2

30

130

0

6

20

400

0

3

1

100

0

1

7

120

2

3

8

130

2

4

3

200

1

内部的に、データベースは次のような一時表を作成します。

CREATE TEMPORARY TABLE tt_geography AS
SELECT MAX(country), MAX(state), KEY_VECTOR_CREATE(...) dense_gr_key_geog
FROM   geography
WHERE  state IN ('WA','CA')
GROUP BY country, state

表7-6に、tt_geography一時表の行を示します。USA、WAの組合せに対する稠密グループ化キーは1で、USA、CAの組合せに対する稠密グループ化キーは2です。

表7-6 tt_geography

dense_gr_key_geog

USA

WA

1

USA

CA

2

7.3.4.3 ステップ2: productsディメンションのキー・ベクターと一時表の作成

データベースでは、Acme製品の個々のカテゴリ/サブカテゴリの組合せに対して稠密グループ化キーが作成されます。

たとえば、表7-7では、4がAcme electric switchの稠密グループ化キーです。

表7-7 products表のサンプル行

製造者 カテゴリ サブカテゴリ prod_id dense_gr_key_prod

Acme

スポーツ

バイク

4

1

Acme

スポーツ

ボール

3

2

Acme

電気

電球

1

3

Acme

電気

スイッチ

8

4

products表のキー・ベクターは、表7-8の最後の列で表される配列のようになります。値は、products稠密グループ化キーを表します。たとえば、4はAcme electric switchのオンライン販売を表します。したがって、キー・ベクターは、sales_onlineのどの行がproductsフィルタ基準(Acme製品の販売)を満たすかを示します。

表7-8 キー・ベクター

prod_id geog_id productsのキー・ベクター

8

1

100

4

9

1

150

0

8

2

100

4

4

3

110

1

2

30

130

0

6

20

400

0

3

1

100

2

1

7

120

3

3

8

130

2

4

3

200

1

内部的に、データベースは次のような一時表を作成します。

CREATE TEMPORTARY TABLE tt_products AS
SELECT MAX(category), MAX(subcategory), KEY_VECTOR_CREATE(...) dense_gr_key_prod
FROM   products
WHERE  manuf = 'ACME'
GROUP BY category, subcategory

表7-9に、この一時表の行を示します。

表7-9 tt_products

カテゴリ サブカテゴリ dense_gr_key_prod

スポーツ

バイク

1

スポーツ

ボール

2

電気

電球

3

電気

スイッチ

4

7.3.4.4 ステップ3: キー・ベクター問合せ変換

このフェーズでは、データベースはファクト表を処理します。

オプティマイザは、元の問合せを、キー・ベクターにアクセスする次の同等の問合せに変換します。

SELECT KEY_VECTOR_PROD(prod_id),
       KEY_VECTOR_GEOG(geog_id),
       SUM(amount)
FROM   sales_online
WHERE  KEY_VECTOR_PROD_FILTER(prod_id) IS NOT NULL 
AND    KEY_VECTOR_GEOG_FILTER(geog_id) IS NOT NULL 
GROUP BY KEY_VECTOR_PROD(prod_id), KEY_VECTOR_GEOG(geog_id)

前の変換は、はるかに複雑な内部SQLの正確なレンディションではなく、基本概念を示すように設計された概念的な表現です。

7.3.4.5 ステップ4: ファクト表からの行フィルタ

このフェーズでは、グループ化キーの各組合せの販売量を取得します。

データベースは、キー・ベクターを使用して、ファクト表から不要な行をフィルタで除外します。表7-10では、最初の3列がsales_online表を表します。最後の2列は、geographyおよびproducts表の稠密グループ化キーを提供します。

表7-10 sales_online表の稠密グループ化キー

prod_id geog_id dense_gr_key_prod dense_gr_key_geog

7

1

100

4

9

1

150

8

2

100

4

1

4

3

110

1

1

2

30

130

6

20

400

3

1

100

2

1

7

120

3

2

3

8

130

2

2

4

3

200

1

1

表7-11に示すように、データベースはsales_onlineから、どちらの稠密グループ化キーもnull値でない行のみを取得しており、すべてのフィルタ基準を満たす行が示されています。

表7-11 sales_online表からフィルタされた行

geog_id prod_id dense_gr_key_prod dense_gr_key_geog

2

8

100

4

1

3

4

110

1

1

3

4

200

1

1

7

1

120

3

2

8

3

130

2

2

7.3.4.6 ステップ5: 配列を使用した集計

データベースでは、多次元配列を使用して集計を実行します。

表7-12では、geographyグループ化キーは水平で、productsグループ化キーは垂直です。データベースは、各稠密グループ化キーの組合せの交差部分の値を加算します。たとえば、geographyグループ化キー1productsグループ化キー1の交差部分では、110200の合計は310です。

表7-12 集計配列

dgkp/dgkg 1 2

1

110,200

2

130

3

120

4

100

7.3.4.7 ステップ6: 一時表への再結合

処理の最終ステージでは、データベースが稠密グループ化キーを使用して行を一時表に再結合し、地域とカテゴリの名前を取得します。

結果は次のようになります。

CATEGORY SUBCATEGORY COUNTRY STATE AMOUNT
-------- ----------- ------- ----- ------
electric bulb        USA     CA    120
electric switch      USA     WA    100
sport    ball        USA     CA    130
sport    bike        USA     WA    310 

7.4 IM集計の制御

IM集計は、オプティマイザと統合されます。新しいSQLまたは初期化パラメータが必要となります。IM集計には、追加の索引、外部キーまたはディメンションは不要です。

次のヒントのペアを使用できます。

  • 問合せブロック・ヒント

    VECTOR_TRANSFORMでは、コストにかかわらず、指定した問合せブロックに対してベクター変換を有効にします。NO_VECTOR_TRANSFORMは、指定した問合せブロックからのベクター変換を無効にします。

  • 表ヒント

    次のヒントのペアを使用できます。

    • VECTOR_TRANSFORM_FACTでは、ベクター変換で生成されたファクト表に、指定したFROM式が含まれます。NO_VECTOR_TRANSFORM_FACTでは、ベクター変換で生成されたファクト表から、指定したFROM式が除外されます。

    • VECTOR_TRANSFORM_DIMSでは、ベクター変換で生成された有効なディメンションに、指定したFROM式が含まれます。NO_VECTOR_TRANSFORM_DIMSでは、ベクター変換で生成された有効なディメンションから、指定したFROM式が除外されます。

関連項目:

VECTOR_TRANSFORM_FACTおよびVECTOR_TRANSFORM_DIMSヒントについてさらに学習するには、『Oracle Database SQL言語リファレンス』を参照してください。

7.5 インメモリー集計: 例

この例では、仕事上の問いは「各カレンダ年に販売されたカテゴリごとの製品数はいくつか」というものです。

timesproductsおよびsales表を結合する、次のような問合せを記述します。

SELECT t.calendar_year, p.prod_category, SUM(quantity_sold)
FROM   times t, products p, sales s
WHERE  t.time_id = s.time_id
AND    p.prod_id = s.prod_id
GROUP BY t.calendar_year, p.prod_category;

例7-3 VECTOR GROUP BY実行計画

次の例に、現在のカーソルに含まれる実行計画を示します。ステップ4と8では、ディメンション表timesおよびproductsのキー・ベクターを作成しています。ステップ17と18では、前に作成したキー・ベクターを使用しています。ステップ3、7および15では、VECTOR GROUP BY操作を行っています。

SQL_ID  0yxqj2nq8p9kt, child number 0
-------------------------------------
SELECT t.calendar_year, p.prod_category, SUM(quantity_sold) FROM
times t, products p, sales f WHERE  t.time_id = f.time_id AND
p.prod_id   = f.prod_id GROUP BY t.calendar_year, p.prod_category

Plan hash value: 2377225738
------------------------------------------------------------------------------------------------------
|Id| Operation                           | Name              |Rows|Bytes|Cost(%CPU)|Time|Pstart|Pstop|
------------------------------------------------------------------------------------------------------
| 0|SELECT STATEMENT                     |                         |    |     |285(100)|        | |  |
| 1| TEMP TABLE TRANSFORMATION           |                         |    |     |        |        | |  |
| 2|  LOAD AS SELECT                     |SYS_TEMP_0FD9D6644_11CBE8|    |     |        |        | |  |
| 3|   VECTOR GROUP BY                   |                         |   5|  80 |  3(100)|00:00:01| |  |
| 4|    KEY VECTOR CREATE BUFFERED       | :KV0000                 |1826|29216|  3(100)|00:00:01| |  |
| 5|     TABLE ACCESS INMEMORY FULL      | TIMES                   |1826|21912|  1(100)|00:00:01| |  |
| 6|  LOAD AS SELECT                     |SYS_TEMP_0FD9D6645_11CBE8|    |     |        |        | |  |
| 7|   VECTOR GROUP BY                   |                         |   5| 125 |  1(100)|00:00:01| |  |
| 8|    KEY VECTOR CREATE BUFFERED       | :KV0001                 |  72| 1800|  1(100)|00:00:01| |  |
| 9|     TABLE ACCESS INMEMORY FULL      | PRODUCTS                |  72| 1512|  0  (0)|        | |  |
|10|  HASH GROUP BY                      |                         |  18| 1440|282 (99)|00:00:01| |  |
|11|   HASH JOIN                         |                         |  18| 1440|281 (99)|00:00:01| |  |
|12|    HASH JOIN                        |                         |  18| 990 |278(100)|00:00:01| |  |
|13|     TABLE ACCESS FULL               |SYS_TEMP_0FD9D6644_11CBE8|   5|  80 |  2  (0)|00:00:01| |  |
|14|     VIEW                            | VW_VT_AF278325          |  18| 702 |276(100)|00:00:01| |  |
|15|      VECTOR GROUP BY                |                         |  18| 414 |276(100)|00:00:01| |  |
|16|       HASH GROUP BY                 |                         |  18| 414 |276(100)|00:00:01| |  |
|17|        KEY VECTOR USE               | :KV0000                 |918K|  20M|276(100)|00:00:01| |  |
|18|         KEY VECTOR USE              | :KV0001                 |918K|  16M|272(100)|00:00:01| |  |
|19|          PARTITION RANGE ALL        |                         |918K|  13M|257(100)|00:00:01|1|28|
|20|           TABLE ACCESS INMEMORY FULL| SALES                   |918K|  13M|257(100)|00:00:01|1|28|
|21|    TABLE ACCESS FULL                |SYS_TEMP_0FD9D6645_11CBE8|  5 |  125|  2  (0)|00:00:01| |  |
------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
  11 - access("ITEM_10"=INTERNAL_FUNCTION("C0") AND "ITEM_11"="C2")
  12 - access("ITEM_8"=INTERNAL_FUNCTION("C0") AND "ITEM_9"="C2")

Note
-----
   - vector transformation used for this statement

45 rows selected.