津島博士のパフォーマンス講座 Indexページ ▶▶

 


皆さんこんにちは、先月は関東でも何十年ぶりかという大雪が降りましたが、大丈夫でしたでしょうか。私は帰宅するのに大変な思いをしたので、もう降らないことを願いたいですね。
今回は、第33回の続きとして、オプティマイザ統計のOracle Database 12c(Oracle12c)新機能の続きとパラレル収集について説明しますので、参考にしてください。

1. Oracle Database 12c 新機能の続き
まずは、オプティマイザ統計関連のOracle12c 新機能の続きについて説明しましょう。
第33回の「2. Oracle Database 12cの新機能 (2)オプティマイザ統計の収集」では、「バルク・ロードのオンライン統計収集」のみの説明でしたので、その続きとして以下について説明します。

  • 一時表のセッション固有統計
  • オプティマイザ統計の同時収集の拡張(「オプティマイザ統計のパラレル収集について」を参照)
  • ヒストグラムの拡張
  • SPM展開アドバイザ

(1)一時表のセッション固有統計
一時表(Global Temporary Table)のセッション固有統計から説明します。
一時表は、第11回で説明したように、各セッションのデータを同じテーブル名で処理できるので、同一テーブル名を使用するすべてのセッションで、一つのオプティマイザ統計(統計)を共有します。つまり、どれか一つのセッションで収集された統計になるので、すべてのセッションの統計を正確にすることはできません(詳細は、「一時表について」を参照してください)。そのため、Oracle12cから以下のように、それぞれのセッションで固有の統計を管理できるようになっています。


tsushima-35-1

これで、それぞれのセッションの統計を管理できますが、各セッションで収集するようにアプリケーションに組み込む必要があるのは変わりません。例えば、上記のセッション3のように管理セッション(何もデータを挿入していないセッション)などで行っても、行数が0(NUM_ROWS=0)の統計になるだけになります。これは、セッションごとにデータが異なるように管理されているので、それぞれのセッションのデータしかアクセスできないからです(このようなことを知らない方も多いように思います)。

Oracle12cからの統計プリファレンス・パラメータGLOBAL_TEMP_TABLE_STATSを、以下のように一時表に対して’SESSION’にすることで、セッション固有統計に設定できます(デフォルトは’SESSION’です)。このパラメータを’SHARED’にするとOracle Database 11g(Oracle11g)までと同様の共有統計になります。

SQL> exec DBMS_STATS.SET_TABLE_PREFS(NULL,'tab1','GLOBAL_TEMP_TABLE_STATS','SESSION');

このセッション固有統計は、以下の二つについても使用できるようになっています。

  • トランザクション固有一時表
    DBMS_STATS.GATHER_TABLE_STATSを行ってもトランザクションがCOMMITされないので、正しく統計収集できます。
  • バルク・ロードのオンライン統計収集
    第33回で説明したバルク・ロードのオンライン統計収集も使用できます(一時表にバルク・ロードを行うと統計を収集する必要がありません)。

一時表(Global Temporary Table)について
ご存知ない方のために、ここで一時表について簡単に説明します。
一時表は、第11回で説明したように、REDOログの出力を削減できるやTruncate文でチェックポイントを行わない、同じテーブル名に対してセッション固有のデータが使用できるなどのメリットがあります。そのため、中間データの格納などには便利なテーブルで、データの削除するタイミングによって、トランザクション固有(COMMITで削除される)とセッション固有(セッション終了時に削除される)があります。ただし、以下のような制限もあるので、使用するときは少し注意が必要です。

  • パーティション表、索引構成表などが使用できない
  • パラレルUPDATE、DELETEおよびMERGEは使用できない(索引があるとパラレルINSERTもできない)
  • 第20回で説明したIn-Memory PXが使用できない
  • Exadata Storage ServerのFlash Cacheが使用できない(Exadataのみ)
  • 第28回で説明したEHCCの表圧縮が使用できない(Exadataのみ)

一時表に対する統計については、第5回で説明した動的サンプリング以外に、正確な統計を収集するのは難しくなります。これは、一時表はセッションごとにデータを管理するので、各セッションで統計を収集する必要があります(つまり、アプリケーションに組込む必要があります)。ただし、以下のように統計が共有されているので、反映されるのは最後に収集したセッションのデータになります(以下の例は、tmp1の統計がセッション1→セッション2→セッション1と変化しています)。つまり、検索する前に統計を収集しないと、正確にすることができないので、動的サンプリングの方が最適ということです。

tsushima-35-2
 

トランザクション固有一時表では、DBMS_STATS.GATHER_TABLE_STATSを行うとトランザクションがCOMMITされるので、行数が0になってしまい正しい統計を収集できません。そのため、動的サンプリングでしか収集できないので注意して下さい。

 

(2)ヒストグラムの拡張
次に、第27回で説明したヒストグラムも改善されているので、それについて説明します。
個別値がバケット数をオーバーしたときの高さ調整済ヒストグラムは、第27回で説明したように正確に把握することができないので、Oracle12cから以下のように拡張されています。

  • 最大バケット数を2048
    頻度ヒストグラムの対象範囲を増やすために、最大バケット数を254から2048に拡張しています。
  • 上位頻度ヒストグラム
    個別値がバケット数より多い場合でも、少数のデータが大部分を占める(内部的な閾値を超えている)場合に、上位だけを頻度ヒストグラムで行うことで正確にします。
  • ハイブリッド・ヒストグラム
    上位頻度ヒストグラムの条件から外れる場合に、高さ調整済ヒストグラムと頻度ヒストグラムの組合せで行います。高さ調整済ヒストグラムを行った後に、複数のバケットに格納されている値を最初のバケットに集めて数を持つことで、重複が多い値をより正確にします。

高さ調整済ヒストグラムとハイブリッド・ヒストグラムについて
高さ調整済ヒストグラムとハイブリッド・ヒストグラムの違いについて簡単に説明します。
高さ調整済ヒストグラムは、それぞれのバケットにソート後のデータを同じ行数だけ入れて、以下のようにエンドポイント値(バケット0は最小値、それ以外のバケットは最大値)を使用して、バケット1から各バケットに格納される値を管理します。このときバケット内の値は、均等にして数を求めます。複数のバケットでエンドポイント値が同じになる場合は、領域削減のため最後のバケット以外は省略します(バケット番号’ENDPOINT_NUMBER’が抜けます)。このような値をポピュラー値(他の値より多く存在する値)と呼びます。

tsushima-35-3

このときのバケット2と3の大部分に値’11’が占めるような場合は、正確に見積もることができません(二つ目のバケットに存在することが分からないからです)。そのため、以下のように最初のバケットに集めて数を管理することで、正確に見積もれるようにしたのが、ハイブリッド・ヒストグラムになります。

tsushima-35-4

 

(3)SPM展開アドバイザ(SPM Evolve Advisor)
次に、第5回で説明したSPMも拡張されているので、それについて説明します。
SPMは、実行計画の管理を効率的に行いますが、新たな実行計画は実行計画履歴に格納されて未承認になります。この未承認の実行計画から承認済みの実行計画(SQL計画ベースライン)にするには、管理者によってdbms_spm.evolve_sql_plan_baselineファンクション(未承認の実行計画を承認済みの実行計画と比較して、パフォーマンスが優れている場合に、SQL計画ベースラインとして登録します)などを実行する必要がありました。そのため、新たな実行計画が最適であっても、すぐに採用することができませんでした(これは、SPMの利用目的としては問題ないですが、管理者の負荷が増えることになります)。
Oracle12cからSPM展開アドバイザ・タスク(SYS_AUTO_SPM_EVOLVE_TASK)が導入され、スケジュールされているメンテナンス・ウィンドウで実行されます。このタスクで最もコストの低い実行計画を選択して、既存のプランより性能が良ければ自動的に承認されるようになります。これにより実行計画の管理が容易になります。このSPM展開アドバイザ・タスクの動作は、展開タスク・パラメータで変更することが可能です。例えば、以下のようにACCEPT_PLANSパラメータを’FALSE’に設定すると(デフォルトは’TRUE’です)、タスクは実行計画を検証して、そのレポートを生成しますが、実行計画の承認は行わないようになります。

SQL> EXEC dbms_spm.set_evolve_task_parameter('SYS_AUTO_SPM_EVOLVE_TASK','ACCEPT_PLANS','FALSE');

展開タスク・パラメータを確認するには、以下のようなSQLで行うことが可能です。

SQL> SELECT PARAMETER_NAME, PARAMETER_VALUE AS "VALUE" FROM DBA_ADVISOR_PARAMETERS
2  WHERE TASK_NAME = 'SYS_AUTO_SPM_EVOLVE_TASK' AND PARAMETER_NAME IN ('ACCEPT_PLANS','TIME_LIMIT');

PARAMETER_NAME            VALUE
------------------------- ----------
TIME_LIMIT                3600
ACCEPT_PLANS              TRUE

このSPM展開アドバイザは、自動SQLチューニング・アドバイザと共に有効化または無効化されます。

2. オプティマイザ統計のパラレル収集について
最後に、統計のパラレル収集について説明しましょう。統計のパラレル収集については、まだ説明していなかったので、少しまとめて説明します。
統計の収集を短時間で行うには、他の処理と同じようにパラレルで行う必要があるので、dbms_statsパッケージではパラレル収集が可能になっています。この統計のパラレル収集には、オブジェクト内パラレル化(DEGREEパラメータ)とOracle11gR2からのオブジェクト間パラレル化(CONCURRENTパラメータ)があるので、それぞれについて説明していきます。

(1)オブジェクト内パラレル
オブジェクト内パラレルは、一つのオブジェクト(テーブル、索引など)に対して、以下のようにパラレル・スレーブ・プロセスを使用してパラレルに実行します(第20回で説明したパラレル実行を行います)。そのため、大きなオブジェクトでないと効果がないので、オブジェクトのブロック数が少ないとパラレルで動作しないようになっています。


tsushima-35-5

統計収集するときに、DEGREEパラメータでパラレル度を制御します。デフォルトのNULLでは、CREATE TABLE文などのDEGREE句で指定されたデフォルト値が使用されます。以下のように’DBMS_STATS.AUTO_DEGREE’を指定することで、オブジェクトのサイズによって適切なパラレル度に調整するので、基本はこれを使用します。

SQL> EXEC dbms_stats.gather_table_stats(NULL,'tab1',DEGREE=>'DBMS_STATS.AUTO_DEGREE');

(2)オブジェクト間パラレル
オブジェクト間パラレルは、小さいオブジェクトでもパラレル実行できるように、複数のオブジェクトを同時収集する機能です(統計の同時収集機能と呼びます)。それぞれの収集が以下のようにジョブとして動作して、パーティションやサブパーティションも同時に収集することができます(ただし、パーティションが非常に小さい場合などは、そのようなオブジェクトを自動的に一つのジョブにまとめる場合もあります)。パーティションの収集は、コーディネーター・ジョブが動作して、その下で各パーティションのジョブとグローバル統計のジョブが動作します。このときのジョブの最大数は、初期化パラメータJOB_QUEUE_PROCESSESと使用可能なリソースによって決まります。


tsushima-35-6

Oracle11gまでは、自動オプティマイザ統計収集(自動統計収集)で使用できない、複数のパーティション表を同時に行えないなどの制限があるので、あまり使いやすいとは言えませんでした。そのため、Oracle12cからは、複数のパーティション表と自動統計収集時にも統計の同時収集が可能になり、統計の収集時間を短縮することが簡単で効率的に行えます。
自動統計収集を可能にするために、Oracle12cから統計プリファレンス・パラメータCONCURRENTに設定する値が、以下のように変更になっています(Oracle11gまでは’TRUE’と’FALSE’だけです)。

  • ‘MANUAL’(手動統計収集時のみ同時収集を行う)
  • ‘AUTOMATIC’(自動統計収集時のみ同時収集を行う)
  • ‘ALL’(自動統計収集と手動統計収集で同時収集を行う)
  • ‘OFF’(同時収集を行わない。これがデフォルトです)

以下のように’ALL’に設定することで、自動統計収集と手動統計収集で同時収集が可能になるので、基本はこれで問題ありません。

SQL> EXEC dbms_stats.set_global_prefs('CONCURRENT','ALL');

ただし、同時統計収集のジョブでは、使用されるリソースを明示的に管理することができないので、リソースをすべて使用する場合があります。そのため、Oracle Database Resource Manager(リソース・マネージャ)でジョブの使用するリソースの上限を設定する必要があります。デフォルトでは、メンテナンス・ウィンドウ中に自動実行されるメンテナンス・タスクで、リソース・マネージャがアクティブになります(Oracle11gからリソース・プラン’DEFAULT_MAINTENANCE_PLAN’が設定されます)。つまり、Oracle12cからの自動統計収集で同時収集を行うと、デフォルトでリソース管理されます。このようなことも使いやすくなった要因です(リソース・マネージャの説明は別の機会にします)。

(3)オブジェクト内パラレルとオブジェクト間パラレル
オブジェクト内パラレルとオブジェクト間パラレルは、同時に指定することも可能です。オブジェクト内パラレル収集は、それぞれのパーティションをパラレルに収集しますが、パーティションを同時に収集することはできません。そのため、大規模なパーティション表(それぞれのパーティションのサイズが大きいとき)は、以下のように二つのレベルのパラレル処理で、収集時間を短縮することが可能です。


tsushima-35-7

そのような場合には、パラレル度がダウン・グレードされないように、初期化パラメータPARALLEL_ADAPTIVE_MULTI_USERを以下のように’FALSE’にしてください。

SQL> ALTER SYSTEM SET PARALLEL_ADAPTIVE_MULTI_USER = FLASE;
 

3. おわりに
今回はオプティマイザ統計のOracle12c新機能の続きとパラレル収集について説明しましたが、少しは参考になりましたでしょうか。また機会があれば他のことについても説明したいと思います。これからもよろしくお願いします。
それでは、次回まで、ごきげんよう。

 


ページトップへ戻る▲ 

 

津島博士のパフォーマンス講座 Indexページ ▶▶