Oracle Database 12c Release...

31
Oracle Database 12c Release 2オプティマイザ統計 Oracle ホワイト・ペーパー | 2017 年 3 月

Transcript of Oracle Database 12c Release...

Page 1: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

Oracle Database 12c Release 2の オプティマイザ統計 Oracle ホワイト・ペーパー | 2017 年 3 月

Page 2: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

Oracle Database 12c Release 2 のオプティマイザ統計について

目次

概要 ................................................................................................................................................................... 1

オプティマイザ統計とは .............................................................................................................................. 2

パーティション表での統計 ........................................................................................................................ 12

統計の管理 ..................................................................................................................................................... 16

その他のタイプの統計 ................................................................................................................................ 22

結論 ................................................................................................................................................................. 27

参考資料 ......................................................................................................................................................... 28

Page 3: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

1 | Oracle Database 12c Release 2 のオプティマイザ統計について

概要

Oracle データベースが初めて登場したときには、SQL 文の実行方法はルールベース・オプティマイザ(RBO)によって決定されていました。ルールベース・オプティマイザでは、その名前が示すように、一連のルールに従って SQL 文の実行計画が決定されていました。

Oracle Database 7 では、Oracle Database に当時追加されたパラレル実行やパーティション化などの拡張機能に対処するため、そして実際のデータ・コンテンツとデータ分布を考慮するために、コストベース・オプティマイザ(CBO)が導入されました。コストベース・オプティマイザは、SQL 文に対して考えられるすべての計画を調査し、コストのもっとも低い計画を選択します。ここで、コストとは、特定の計画における推定リソース使用率のことです。コストが低いほど、実行計画の効率が高くなることが期待されます。コストベース・オプティマイザが実行計画のコストを正確に判断するためには、オプティマイザは SQL 文でアクセスするすべてのオブジェクト(表と索引)に関する情報と、SQL 文を実行するシステムに関する情報を利用する必要があります。

必要となるこの情報は一般に、オプティマイザ統計と呼ばれます。オプティマイザ統計を理解して管理することが、最適な SQL 実行の達成に極めて重要です。このホワイト・ペーパーは、オプティマイザ統計に関する 2 部構成シリーズの 1 部目となっており、統計の重要な概念、Oracle Optimizer で使用される統計のタイプについて説明します。シリーズ第 2 部(『Best Practices for Gathering Optimizer Statistics with Oracle Database 12c』)では、データベースに保管されているデータを正確に表せるように、オプティマイザ統計を最新の状態に保つ方法について説明します。

Page 4: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

2 | Oracle Database 12c Release 2 のオプティマイザ統計について

オプティマイザ統計とは

オプティマイザ統計は、データベースおよびデータベース内のオブジェクトを説明するデータのコレクションです。これらの統計は、各 SQL 文に最適な実行計画を選択するために、オプティマイザによって使用されます。統計はデータ・ディレクトリに格納され、USER_TAB_STATISTICS などのデータ・ディクショナリ・ビューを使用してアクセスできます。

図1:データ・ディクショナリに格納されたオプティマイザ統計をOracle Optimizerが使用し、実行計画を決定

オプティマイザ統計のほとんどのタイプは、データベースに保管されたデータの性質を正確に表すために、定期的に収集または更新する必要があります。たとえば、データベース内のデータがすぐに変更される場合は(速いテンポで継続的に入力される表があるなど)、データがあまり変更されない場合よりも頻繁に統計を収集する必要があります。データベース管理者は、手動または自動プロセスを使って統計を収集でき、その方法については、シリーズ第 2 部で紹介します 1。

表統計と列統計の情報

表統計情報には、表内の行数、表に使用されるデータ・ブロックの数、および表内の行の長さの平均などの情報が含まれます。オプティマイザはこの情報を他の統計とともに使用することで、実行計画のさまざまな操作のコストを計算し、操作によって生成される行の数を見積ります。たとえば、表 ア ク セ ス の コ ス ト は 、 デ ー タ ・ ブ ロ ッ ク の 数 と パ ラ メ ー タDB_FILE_MULTIBLOCK_READ_COUNT の値を組み合わせて使用して計算されます。表統計はディクショナリ・ビューUSER_TAB_STATISTICS で参照できます。

列統計情報には、列内の個別値(NDV)の数、および列内で検出された最大値と最小値に関する情報が含まれます。列統計情報は、ディクショナリ・ビューUSER_TAB_COL_STATISTICS で参照できます。オプティマイザは、列統計情報を表統計(行数)とともに使用することで、SQL 操作で返される行数を予測します。たとえば、表に 100 のレコードが含まれており、10 の個別値が含まれた列の等価条件を表アクセスによって評価する場合、オプティマイザはデータが均一に分布しているとみなして、表内の行数を列の個別値数で割った値(100/10 = 10)をカーディナリティの見積りとします。

1 Oracle ホワイト・ペーパー:『Best Practices for Gathering Optimizer Statistics with Oracle Database 12c Release 2』

Page 5: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

3 | Oracle Database 12c Release 2 のオプティマイザ統計について

図2:基本的な表統計と列統計の情報を使用したカーディナリティの計算

その他の列統計情報

基本的な表統計と列統計の情報は多くの情報をオプティマイザに示しますが、表または列に含まれたデータの性質に関する情報をオプティマイザに示すためのメカニズムはありません。たとえば、表統計と列統計の情報はオプティマイザに対して、列のデータに偏りがあるかどうかや、表内の列間に相関関係があるかどうかを示すことはできません。この種の情報は、基本統計の拡張を使って収集できます。そのような拡張には、ヒストグラム、列グループ、式の統計があります。これらの拡張を使用しない場合、オプティマイザはデータの値が均一に分布し、列の値の間に相関関係がないものとみまします。

ヒストグラム

ヒストグラムは、列内のデータの分布についてオプティマイザに示します。デフォルト(ヒストグラムを使用しない)では、オプティマイザは列内の個別値について、行が均一に配分されているとみなします。前述のとおり、オプティマイザは、表内の行の総数を等価条件に使用されている列内の個別値数で割ることで、等価条件のカーディナリティを計算します。列内のデータ分布が均一でない(データに偏りがある)と、カーディナリティの見積りは正しくなりません。不均一なデータ分布を正確に反映するためには、列にヒストグラムが必要になりす。ヒストグラムを使用することで、オプティマイザが使用する計算式はより正確なカーディナリティを見積るように変更され、オプティマイザによってさらに精度の高い実行計画が生成されます。

Oracle では、列の使用状況の情報(SYS.COL_USAGE$)に基づいて、ヒストグラムを必要とする列とデータの偏りが自動的に特定されます。たとえば、一意の列が等価条件にのみ表れる場合は、その一意の列に対してヒストグラムは自動的には作成されません。

ヒストグラムには、頻度ヒストグラム、上位頻度ヒストグラム、高さ調整済ヒストグラム、ハイブリッド・ヒストグラムの 4 種類があります。ヒストグラムの適切なタイプが Oracle データベースによって自動的に選択されます。この選択は、列内の個別値の数に基づいて行われます。Oracle Database 12c 以降では、高さ調整済ヒストグラムがハイブリッド・ヒストグラムに置き換わっています 2。データ・ディクショナリ・ビューの user_tab_col_statistics には“histogram”という列が含まれています。この列は、特定の表の列にあるヒストグラムのタイプを示します。

2 統計の収集に使用する DBMS_STATS.GATHER_*_STATS コマンドで、パラメータ ESITMATE_PERCENT が“AUTO_SAMPLE_SIZE”に設定されているこ

とが前提であり、これがデフォルトです。

Page 6: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

4 | Oracle Database 12c Release 2 のオプティマイザ統計について

頻度ヒストグラム

頻度ヒストグラムは、列内の個別値の数が、許可されたバケットの最大数を下回る場合に作成されます。この値はデフォルトで 254 になっていますが、DBMS_STATS プロシージャを使用すると、最大 2048 まで変更できます(Oracle Database 12c 以降)。

図 3 は、頻度ヒストグラムを使って、列“COL1”のデータ分布をエンコードして表した状態を示しています。グラフ 1(左側)では、各値の列(バケット)があり、列の高さはその特定の値の COUNTを表します。オラクルの頻度ヒストグラムとは、“エンド・ポイント値”としてのバケットをいい、累積度数は“エンド・ポイント番号”として格納されます(図 2 を参照)。このケースでは、"40"のエンド・ポイントに 10 が格納されます。次に、“51”のエンド・ポイントに 10+1(11)が格納され、続いて“52”に 11+2(13)が格納され、この操作が繰り返されます。

図3:ヒストグラムを使ったデータ分布の表示

図 4 は、このヒストグラムがデータ・ディクショナリでどのように表示されるかを示しています。グラフ 2 の ENDPOINT_VALUE および ENDPOINT_NUMBER とグラフ 1 の FREQUENCY を比較してください。

図4:データ・ディクショナリでのヒストグラムの表示

エンド・ポイント値は数値であるため、数値以外のデータ型を持つ列のヒストグラムの値は、数値にエンコードされています。

ヒストグラムが作成されると、オプティマイザはそのヒストグラムを使ってカーディナリティをより正確に見積もります。たとえば、“WHERE val = 53”という条件がある場合、もちろん、ヒストグラムを使って(エンド・ポイント値"53"を使用)、カーディナリティが 3 になると見積もることができます。頻度ヒストグラムにない値の条件(“WHERE val=41”など)の場合は、カーディナリティは 1 の見積り値になります。これは、オプティマイザによってコスト計算用に、“1 行返された場合”と“ゼロ行返された場合”の両方に対して選択された最低限の数値です。

Page 7: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

5 | Oracle Database 12c Release 2 のオプティマイザ統計について

高さ調整済ヒストグラム

Oracle Database 12c 以前では、高さ調整済ヒストグラムが、個別値の数が許可されたバケットの最大数(デフォルトでは 254 ですが、DBMS_STATS プロシージャを使って変更可能です)を上回る場合に作成されます。頻度ヒストグラムは、個別値の数が大きくなるとあまり役に立たなくなります。なぜなら頻度ヒストグラムでは、ヒストグラム・バケットごとに 1 つの値が格納され、ヒストグラム・バケットの数が増えるとヒストグラムの格納、使用、維持に要するシステム・オーバーヘッドが増大するからです。Oracle Database 12c ではほとんどの場合、高さ調整済ヒストグラムの代わりにハイブリッド・ヒストグラムが作成されます。ハイブリッド・ヒストグラムについては、後の項で説明します。

1~1000 の値を持つ列“COL1”が表にあるとします。図 5 は、範囲 1~1,000 を一連の同一の範囲(それぞれが 100 の値範囲を表す 10 の範囲)に分割することで、データ分布を表す方法を示します。1~100 の値の行が 1,000 行あり、201~300 の間の値で行数(3,000)が跳ね上がっています。

図5:頻度ヒストグラム

図 6 に示すように、"高さ調整済"ヒストグラムを使って、図 5 とまったく同じ情報をエンコードすることができます。範囲のサイズを調整することで、各範囲を同様に行数にすることが可能です。言いかえれば、それぞれの縦"棒"の高さがほぼ同じ並びになります。たとえば、範囲 1~200 に2,000 行があるとします。上の図で分かるように、201~300 の値の行はこれよりも多いので、行数を約 2,000 行にするには、次の範囲(201~267)を狭める必要があります。

図6:図5と同じデータを使って作成された高さ調整済ヒストグラム

Page 8: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

6 | Oracle Database 12c Release 2 のオプティマイザ統計について

ヒストグラムの詳細は、データ・ディクショナリから問い合わせることができます。バケットの数を 6 にしたため、この例はやや無理がありますが、以下の一覧を短くするためにこの設定にしました。図 7 を見て、列の最小値“1”を示すエンド・ポイント番号"0"に注目してください。

図7:高さ調整済ヒストグラムの詳細の表示

多くの場合、エンド・ポイントの番号は連続していません。オプティマイザにより、複数のバケットが 1 つのバケットに"圧縮"されて、バケットの総数が減らされることがあるためです。以下の例では、エンド・ポイント番号 3 がありません(値 500 と 501 は非常に一般的です)。

図8:バケットの圧縮

表内の列の値が非常に多くある場合は、複数のヒストグラム・バケットにまたがることがあります。それは、このタイプのヒストグラムの場合、すべてのバケットにほぼ同じ数の行を含める必要がありますが、一般的、つまり"ポピュラー"な列の値が多すぎて、その頻度がバケットあたりの最大行数を超過することがあるためです。このようなよくある列の値は実際、ポピュラー値と呼ばれ、その多さを見越してオプティマイザによってさまざまに処理されます。ただし、場合によっては、1つの値がほぼ 2 つのバケットにまたがることがあり、これらはほぼポピュラーな値と呼ばれます。ほぼポピュラーな値のコスト計算は不正確になる可能性があります。そのため、Oracle Database 12c では、この制限に対処するためにハイブリッド・ヒストグラム(後で説明します)が導入されました。

上位頻度ヒストグラム

従来では、列の個別値が、使用可能なバケットの数(デフォルトで 254)を上回る場合、高さ調整済ヒストグラムまたはハイブリッド・ヒストグラムが作成されます。ただし、表内のほとんどの行の個別値が少なめで、その他の行(個別値が多い行)の割合が全体的に非常に小さい場合があります。そのような場合、表内の行の大半に対して頻度ヒストグラムを作成しつつ、統計的に有意ではない一連の行(カーディナリティが低く、個別値が多い行)を無視した方が適切なことがあります。頻度ヒストグラムを選択するには、列内の個別値の数が“n”を超過していても、ヒストグラム・バケットの数"n"が、カーディナリティを正確に計算する上で十分かどうかをデータベースで判別する必要があります。それには、問題の列について表内の上位行 99.6%にいくつ個別値があるかを計算

Page 9: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

7 | Oracle Database 12c Release 2 のオプティマイザ統計について

します(デフォルトでは 99.6%ですが、この値は、ヒストグラムの使用可能なバケット数を勘案して調整されます)。上位 n 個の個別値を収容するためのヒストグラム・バケットが十分にある場合は、これらのポピュラー値に対して頻度ヒストグラムが作成されます。

上 位 頻 度 ヒ ス ト グ ラ ム は 、 統 計 収 集 コ マ ン ド の ESTIMATE_PERCENT パ ラ メ ー タ がAUTO_SAMPLE_SIZE(デフォルト)に設定されている場合のみ作成されます。これは、必要な条件(行の 99.6%で、含まれている個別値が 254 個以下である)を満たしているかどうかを判断するために、列内のすべての値を確認する必要があるためです。

例として、クリスマス・オーナメント会社の売上げ情報が含まれている PRODUCT_SALES 表についてみてみます。表には、178 万の行と 632 個の個別値 TIME_ID が含まれています。ただし、大部分のクリスマス・オーナメントは毎年 12 月に販売されるため、PRODUCT_SALES の大部分の行では、含まれている個別値 TIME_ID は 254 個以下です。オプティマイザが列内のデータの偏りを認識するためには、TIME_ID 列にヒストグラムが必要です。このケースでは、254 個のバケットが含まれた上位頻度ヒストグラムが作成されます。

図 9 に、上位頻度ヒストグラムの背景にある考え方を示します。原則として、もっとも重要なデータ(点線内)を特定し、そのデータと値を使って頻度ヒストグラムを作成することができます。

図9:上位頻度ヒストグラム

ハイブリッド・ヒストグラム

高さ調整済ヒストグラムに伴うある顕著な問題は、ポピュラー値が 2 つのバケットにまたがっていても、1 つのバケットのエンド・ポイントの値としてしか表示されない可能性があることです。これは、前述の"高さ調整済ヒストグラム"の項で説明した"ほぼポピュラーな値"のシナリオです。

この制限を解決するため、Oracle Database 12c ではハイブリッド・ヒストグラムを導入しています。ハイブリッド・ヒストグラムは、列内の個別値の数が 255 個以上の場合に作成されるため、従来の高さ調整済ヒストグラムと似ています。ただし、似ているのはこの点だけです。ハイブリッド・ヒストグラムでは、値は複数のバケットのエンド・ポイントとはならないため、ヒストグラムに高さ調整済ヒストグラムよりも多くのエンド・ポイント値を含めることができ、事実上、さらに多くのバケットを含めることができます。それでは、ハイブリッド・ヒストグラムでは、ポピュラー値はど の よ う に 示 さ れ る の で し ょ う か 。 各 エ ン ド ・ ポ イ ン ト 値 の 頻 度 が ( 新 し い 列endpoint_repeat_count に)記録されるため、各エンド・ポイント値がどの程度ポピュラーなのかが正確に示されます。

Page 10: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

8 | Oracle Database 12c Release 2 のオプティマイザ統計について

図 10 は、ハイブリッド・ヒストグラムに頻度ヒストグラムと高さ調整済ヒストグラム双方の特性が出ていることを示しています。バケットには複数の値を含めることができ、エンド・ポイント番号には累積度数が格納されます。

図10:ハイブリッド・ヒストグラム

エンド・ポイント繰り返し回数は、エンド・ポイントの値が何回繰り返されているかを示します。たとえば、以下の結果と図 10 のエンド・ポイントの値を比較します。

図11:エンド・ポイントの繰り返し回数について

前 述 の と お り 、 ハ イ ブ リ ッ ド ・ ヒ ス ト グ ラ ム は 、 デ フ ォ ル ト の ESTIMATE PERCENT 設 定(ESTIMATE_PERCENT => DBMS_STATS.AUTO_SAMPLE_SIZE)を使用して統計を収集するときに、列に 255 個以上の個別値が含まれる場合の新しいデフォルトのヒストグラム・タイプとなっています。

拡張統計

Oracle Database 11g では、列統計情報の拡張が導入されました。拡張統計には、列グループの統計と式の統計という 2 種類の追加の統計が含まれます。

列グループ

実際のデータでは、同じ表内の別々の列に格納されているデータ間にリレーションシップ(相関関係)が存在することが多いです。たとえば、CUSTOMERS 表では、カリフォルニア州はアメリカ合衆国にのみ含まれるため、CUST_STATE_PROVINCE 列の値は COUNTRY_ID 列の値に影響を受けます。基本的な列統計情報のみ使用する場合、オプティマイザはこのような実際のリレーションシップを認識できないため、同じ表の複数の列を文の where 句に使用するときにカーディナリティが正しく計算されない可能性があります。実際のリレーションシップをオプティマイザが認識できるようにするには、これらの列に対してグループとして拡張統計を使用します。

Page 11: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

9 | Oracle Database 12c Release 2 のオプティマイザ統計について

列のグループに対して統計を作成すると、同じ表の複数の列を SQL 文の where 句に一緒に使用している場合に、オプティマイザがカーディナリティ見積りを適切に計算できます。統計をグループとして収集する列グループを定義するには、関数 DBMS_STATS.CREATE_EXTENDED_STATS を使用します。列グループを作成した場合、表で統計を収集すると、通常の列の場合と同じように、その列グループの統計が自動的に保持されます(図 12)。

図12:CUSTOMERS表での列グループの作成

列 グ ル ー プ を 作 成 し て 統 計 を 再 収 集 す る と 、 デ ィ ク シ ョ ナ リ ・ ビ ュ ーUSER_TAB_COL_STATISTICS に、システム生成された名前が付いた追加の列が表示されます。この新しい列は、列グループを表します(図 13)。

図13:USER_TAB_COL_STATISTICSで表示される、システムによって生成された列グループ列名

システムによって生成された列名を列グループにマップしたり、他のどの拡張統計がユーザー・スキーマ用に存在するかを確認するには、ディクショナリ・ビューUSER_STAT_EXTENSIONS を問い合わせることができます。

図14:USER_STAT_EXTENSIONSに格納されている列グループに関する情報

Page 12: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

10 | Oracle Database 12c Release 2 のオプティマイザ統計について

オプティマイザでは、country_id='US' and cust_state_province='CA'条件などに列グループ統計を使用するようになります(WHERE 句の条件で一緒に使用される場合)。列グループに含まれているすべての列が SQL 文に含まれていなくても、オプティマイザは拡張統計を使用できます。列のサブセットのみ必要となります。

自動列グループ検出

最適な実行計画を達成するためには、列グループの統計は非常に役立ち、必要となることが多いですが、特定のワークロードに対してどの列グループ統計を作成すればよいかを把握するのが難しい場合があります。

自動列グループ検出は、特定のワークロードに基づいて、どの列グループが表に有益なのかを自動的に判断します。この機能では、関数でラッピングされた列の拡張統計は作成されません。この機能は、列グループのみ対象としています。自動列グループ検出は、次の簡単な 3 段階のプロセスになっています。

ステップ 1:列使用状況をシードする

Oracle は、適切な列グループを判断するために、代表的なワークロードを監視する必要があります。ワークロードを指定するには、SQL Tuning Set を使用するか、実行中のシステムを監視します。ワークロードを示し、そのワークロードをどのくらいの時間監視するかを指定するには、プロシージャ DBMS_STATS.SEED_COL_USAGE を使用します。次の例では、現システムの監視を 5 分間、つまり 300 秒間オンにしています。

監視プロシージャによって、sys.col_usage$で確認されている従来の列の使用状況情報とは異なる情報が記録され、sys.col_group_usage$に保存されます。監視時間枠に実行されて解釈された す べ て の SQL 文 の 情 報 が 保 存 さ れ ま す 。 監 視 時 間 枠 が 終 了 す る と 、 新 し い 関 数DBMS_STATS.REPORT_COL_USAGE を使用して、特定の表に対して記録された列使用状況情報を確認できます。この関数によって、ワークロードのフィルタ条件、結合条件、および group by 句で確認された表の列を一覧表示したレポートが生成されます。

begin dbms_stats.seed_col_usage(null,null,300);

end; /

select dbms_stats.report_col_usage(user,'CUSTOMERS') from dual;

Page 13: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

11 | Oracle Database 12c Release 2 のオプティマイザ統計について

DBMS_STATS.REPORT_COL_USAGE を実行してスキーマ名だけ指定し、表名に NULL を指定して、特定のスキーマのすべての表のレポートを表示することもできます。

ステップ 2:列グループを作成する

各表に対して DBMS_STATS.CREATE_EXTENDED_STATS 関数をコールすると、監視時間枠で取得された使用状況情報に基づいて、必要な列グループが自動的に作成されます。一度拡張統計が作成されると、表で統計が収集されるたびに拡張統計が自動的に保持されます。

または、列グループを DBMS_STATS.CREATE_EXTENDED_STATS 関数に 3 番目の引数として指定して、列グループを手動で作成することもできます。

ステップ 3:統計を再収集する

最後の段階では、新しく作成した列グループに統計が作成されるように、対象となる表で統計を再収集します。

SQL 計画ディレクティブと列グループ

SQL 計画ディレクティブ 3は、オプティマイザの SQL 実行計画に使用されるだけでなく、誤ったカーディナリティ見積りの解決に列グループが有効かを判別するために Oracle でも使用されます。SQL 計画ディレクティブが作成され、誤ったカーディナリティ見積りを列グループで解決できるとオプティマイザが判断した場合、Oracle Database 12c Release 1 は、次回、該当する表の統計が収集された時に、その列グループを自動的に作成します。

この動作は Oracle Database 12c Release 2 で変更されました。列グループの自動作成はデフォルトでオフになっており、AUTO_STAT_EXTENSIONS という DBMS_STATS プリファレンスによって制御されます。プリファレンスは次のように使用します。

列グループの自動作成に SQL 計画ディレクティブは使用されません(デフォルト)。

列グループの自動作成に SQL 計画ディレクティブが使用されます。

DBMS_STATS プリファレンスは、Oracle Database 12c Release 2 に標準搭載されていますが、パッチ 21171382 を Oracle Database 12c Release 1 に適用すると、プリファレンスをこのリリースに追加できます。

3 Oracle ホワイト・ペーパー:『Oracle Database 12c Release 2 のオプティマイザ』を参照

exec dbms_stats.gather_table_stats(null,'CUSTOMERS')

exec dbms_stats.set_global_prefs ('AUTO_STAT_EXTENSIONS', 'OFF');

exec dbms_stats.set_global_prefs ('AUTO_STAT_EXTENSIONS', 'ON');

select dbms_stats.create_extended_stats(user,'CUSTOMERS') from dual;

Page 14: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

12 | Oracle Database 12c Release 2 のオプティマイザ統計について

式の統計

式内に列が組み込まれた where 句の条件のカーディナリティをオプティマイザが見積ることができるように、式(関数を含む)に対して拡張統計を作成できます。たとえば、where 句の条件で、顧客の姓に UPPER 関数(UPPER(CUST_LAST_NAME)=:B1)を使用するのが通常である場合、式UPPER(CUST_LAST_NAME)に対して拡張統計を作成すると役立ちます。

図15:式にも拡張統計を作成可能

列グループと同様に、式の統計を定義したら、表で統計を再収集する必要があります。統計を収集したら、式の統計を表すディクショナリ・ビューUSER_TAB_COL_STATISTICS に、システム生成さ れ た 名 前 が 付 い た 追 加 の 列 が 表 示 さ れ ま す 。 列 グ ル ー プ の 場 合 と 同 様 に 、USER_STAT_EXTENSIONS を使用して式の統計の詳細情報を表示できます。

拡張統計の制限事項

拡張統計は、where 句の条件が等価条件または in リスト条件である場合のみ使用できます。拡張統計は、基本となる列にヒストグラムが使用されており、列グループにヒストグラムが使用されていない場合は使用されません。

索引統計

索引統計には、索引内の個別値の数(個別キー)、索引の深さ(blevel)、索引内のリーフ・ブロックの数(leaf_blocks)、およびクラスタ化係数に関する情報が含まれます。オプティマイザはこの情報を他の統計とともに使用することで、索引アクセスのコストを決定します。たとえば、オプティマイザは b_level、leaf_blocks、および表統計の num_rows を使用することで、索引レンジ・スキャンのコストを決定します(すべての条件が索引の先頭に配置されている場合)。

パーティション表での統計

パーティション表での統計は、表レベルとパーティション・レベルの両方で計算する必要があります。Oracle Database 11g より前のバージョンでは、新しいパーティションを追加したり、少数のパーティションのデータを変更したりするには、表全体をスキャンして表レベルの統計を更新する必要がありました。グローバル・レベルの統計の収集をスキップした場合、既存のパーティション・レベルの統計に基づいてオプティマイザによってグローバル・レベルの統計が推定されます。このアプローチは、行数などの単純な表統計では、すべてのパーティションの個々の行数が集計されるため、精度が高くなりますが、他の統計は正確に特定できません。たとえば、すべてのパーティションの個々の統計に基づいて、列の個別値数(オプティマイザで使用されるもっとも重要な統計の 1 つ)を正確に特定することはできません。

select dbms_stats.create_extended_stats(NULL,'CUSTOMERS','UPPER(CUST_LAST_NAME))') from dual;

Page 15: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

13 | Oracle Database 12c Release 2 のオプティマイザ統計について

Oracle Database 11g では、増分グローバル統計の導入により、パーティション表の統計収集が強化さ れ ま し た 。 パ ー テ ィ シ ョ ン 表 の INCREMENTAL プ リ フ ァ レ ン ス が TRUE に 設 定 さ れ 、DBMS_STATS.GATHER_*_STATS の パ ラ メ ー タ GRANULARITY が GLOBAL に 設 定 さ れ 、ESTIMATE_PERCENT が AUTO_SAMPLE_SIZE に設定されている場合、Oracle により、新しいパーティションで統計が収集され、表全体ではなく、追加または変更のあったパーティションのみをスキャンすることで、グローバル・レベルのすべての統計が正確に更新されます。

増分グローバル統計は、表内の各パーティションのシノプシスを保存することで機能します。シノプシスは、そのパーティションおよびパーティション内の列の統計メタデータであり、各シノプシスは SYSAUX 表領域に格納されます。その後、パーティション・レベルの統計と各パーティションのシノプシスを集計することで、グローバル統計が生成されるため、表レベルの統計を収集するために表全体をスキャンせずに済みます(図 16)。表に新しいパーティションが追加された場合は、新しいパーティションの統計を収集するだけです。新しいパーティションのシノプシスと既存のパーティションのシノプシスを使用して、グローバル統計が自動的かつ正確に更新されます。

図16:レンジ・パーティション表での増分統計の収集

INCREMENTAL 統計はサブパーティションには適用されません。統計は、サブパーティションとパーティションで通常どおりに収集されます。パーティション統計のみ使用して、グローバル・レベルの統計または表レベルの統計が特定されます。以下に、増分グローバル統計を使用するために必要となる手順を示します。 増分統計を有効にし開始: まず、増分統計をオンにします。

デフォルトの ESTIMATE_PERCENT パラメータと GRANULARITY パラメータを使って、オブジェクトで通常どおりに統計を収集します。

BEGIN DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'INCREMENTAL', 'TRUE'); END;

/

BEGIN DBMS_STATS.GATHER_TABLE_STATS('SH', 'SALES'); END;

/

Page 16: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

14 | Oracle Database 12c Release 2 のオプティマイザ統計について

特定の表について INCREMENTAL の現在の設定を確認するには、DBMS_STATS.GET_PREFS を使用します。

増分統計と古くなった統計

Oracle Database 11g では、表の増分統計が有効になっている場合、いずれかのパーティションで単一行が変更されると、このパーティションの統計は古いとみなされました。そのため、グローバル・レベルの統計の生成に使用する前に、このパーティションの統計を再収集する必要がありました。

Oracle Database 12c では、INCREMENTAL_STALENESS と呼ばれる新しいプリファレンスを使用して、パーティション統計が古いとみなされてグローバル・レベルの統計を生成するには十分でなくなるタイミングを制御できます。デフォルトでは、INCREMENTAL_STALENESS は NULL に設定され、単一行が変更されるとすぐに、パーティション・レベルの統計は古いとみなされます(11g と同様)。

このプリファレンスはまた、USE_STALE_PERCENT または USE_LOCKED_STATS に設定することもで き ま す 。 USE_STALE_PERCENT で は 、 変 更 の あ っ た 行 の 割 合 が プ リ フ ァ レ ン スSTALE_PRECENTAGE の値(デフォルトでは 10%)よりも小さい限り、パーティション・レベルの統計が使用されます。USE_LOCKED_STATS では、パーティションの統計がロックされている場合、統計が前回収集されてから該当するパーティション内で変更のあった行数に関係なく、パーティションの統計を使用してグローバル・レベルの統計が生成されます。

増分統計とパーティション交換ロード

パーティション化の利点の 1 つとして、EXCHANGE PARTITION コマンドを使用して、ビジネス・ユーザーへの影響を最小限に抑えながらデータをすばやく簡単にロードできる点があります。EXCHANGE PARTITION コマンドを使用すると、非パーティション表のデータをパーティション表の指定のパーティションに置き換えることができます。このコマンドで、データの物理的な移動は発生しません。代わりに、ポインタをパーティションから表(またはその逆)に変更するようにデータ・ディクショナリが更新されます。

以前のリリースでは、パーティション交換処理時に増分統計をサポートするために必要となる統計を非パーティション表で生成することはできませんでした。代わりに、グローバル統計を徐々に保持できるようにするため、交換が実行されてからパーティションで統計を収集する必要がありました。

Oracle Database 12c では、必要な統計(シノプシス)を交換前に非パーティション表で作成することができます。そのため、パーティション交換ロード時に交換された統計を使用して、グローバル統計を徐々に自動保持できます。新しい DBMS_STATS の表プリファレンス INCREMENTAL_LEVEL

を使用して、パーティション交換ロードに使用される非パーティション表を特定できます。INCREMENTAL_LEVEL を TABLE(デフォルトは PARTITION)に設定すると、統計の収集時に表のシノプシスが自動的に作成されます。この表レベルのシノプシスは、交換がロードされるとパーティション・レベルのシノプシスになります。

次に例を示します。

SELECT DBMS_STATS.GET_PREFS('INCREMENTAL', 'SH', 'SALES') FROM dual;

exec dbms_stats.set_table_prefs ('SH','EXCHANGETAB','INCREMENTAL','TRUE') exec dbms_stats.set_table_prefs ('SH','EXCHANGETAB','INCREMENTAL_LEVEL','TABLE')

Page 17: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

15 | Oracle Database 12c Release 2 のオプティマイザ統計について

シノプシスの機能拡張

大きいパーティション表のあるデータウェアハウス・アプリケーションの場合、増分メンテナンスを利用すると時間が大幅に節約されます。ただし、増分メンテナンスを使用するとパフォーマンスが向上しますが、ディスク・ストレージの使用量の大幅な増加という代償が伴うことがあります。シノプシス情報が SYSAUX 表領域に保存されるためです。パーティション数や列数の多い表、とりわけ個別値数(NDV)が多い表では、シノプシスにより多くのストレージが必要です。ストレージ領域が消費されることに加えて、このように非常に大きいシノプシス情報を維持するために、パフォーマンス・オーバーヘッドが生じる可能性があります。

Oracle Database 12.2 以降、DBMS_STATS が提供する新しいアルゴリズムで NDV 情報が収集されるため、これまでのアルゴリズムと同じレベルの正確性を維持しながらも、シノプシスははるかに小規模になります。

APPROXIMATE_NDV_ALGORITHM という新しい DBMS_STATS プリファレンスを使って、どのタイプのシノプシスが作成されるかを制御します。デフォルト値は REPEAT OR HYPERLOGLOG です。そのため、既存のシノプシスのために既存の適応サンプリング・アルゴリズムが保持されますが、新しいシノプシスは新しい HYPERLOGLOG アルゴリズムによって作成されます。同じ表で新旧スタイルのシノプシスのどちらも一緒に使うことができます。

Oracle Database 12.2 以前のシステム(増分統計を使用するシステム)をアップグレードする場合は、次の 3 つのオプションがあります。

オプション 1 – 12.2 以前のフォーマットの使用を続ける

DBMS_STATS プリファレンスを“adaptive sampling”に変更します。次に例を示します。

オプション 2 – 古いフォーマットをすぐに新しいフォーマットに置き換える

全パーティションで統計が再収集されます。

オプション 3 – 古いフォーマットを段階的に新しいフォーマットに置き換える

古いシノプシスはすぐには削除されず、新しいパーティションに新しいフォーマットのシノプシスが使用されます。フォーマットの混在によって、統計の正確性が落ちる可能性がありますが、このオプションを使用すると、フォアグラウンドですべての統計を再収集する必要がなくなります。新しいフォーマットが使用されるように、統計自動ジョブによって古いシノプシスのあるパーティションで統計が再収集されるためです。最終的には、すべてのシノプシスが新しいフォーマットになり、統計が正確になります。

Oracle Database 12c での新しい実装の場合、新しいフォーマットのシノプシスが使用されるように、デフォルトのプリファレンス値 REPEAT OR HYPERLOGLOG を使用することを推奨します。

EXEC dbms_stats.set_database_prefs ('approximate_ndv_algorithm', 'adaptive sampling')

EXEC dbms_stats.set_database_prefs ('approximate_ndv_algorithm', 'hyperloglog') EXEC dbms_stats.set_database_prefs ('incremental_staleness', NULL)

EXEC dbms_stats.set_database_prefs ('approximate_ndv_algorithm', 'hyperloglog') EXEC dbms_stats.set_database_prefs ('incremental_staleness', 'allow_mixed_format')

Page 18: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

16 | Oracle Database 12c Release 2 のオプティマイザ統計について

統計の管理

適切な統計を収集するだけでなく、統計を管理するための包括的なフレームワークを提供することも同じように重要です。オラクルはこれに対応するために、統計を以前のバージョンにリストアする機能、統計を別のシステムに転送するオプション、統計値を手動で設定するオプションを含め、さまざまな方法を提供しています。これらのオプションは特定のケースで非常に役立ちますが、DBMS_STATS

パッケージを使用する標準の統計収集方法の代わりとして使用することは推奨されません。

統計のリストア

DBMS_STATS を使用して統計を収集すると、元の統計がディクショナリ表にバックアップとして自動的 に 保 持 さ れ る た め 、 新 し く 収 集 し た 統 計 に 問 題 が 発 生 し た 場 合 は 、DBMS_STATS.RESTORE_TABLE_STATS を実行して簡単にリストアできます。ディクショナリ・ビューDBA_TAB_STATS_HISTORY には、各表の統計が格納されたタイムスタンプの一覧が含まれます。

次の例では、表 SALES の統計を前日の状態にリストアし、SALES 表を参照しているすべてのカーソルを SHARED_POOL で自動的に無効化しています。前日の統計をリストアして、前日の統計をすべてのカーソルに瞬時に適用させるために、すべてのカーソルを無効化する必要があります。表を参照しているカーソルが無効化されるかどうかは、NO_INVALIDATE パラメータの値によって決まります。

統計の保留

デフォルトでは、統計は収集されると即座に、該当するディクショナリ表に公開されて(書き込まれて)、オプティマイザによって即時に使用されます。Oracle Database 11g 以降、収集したオプティマイザ統計をすぐには公開せず、代わりに、未公開の'保留'状態で格納することができます。この統計は通常のディクショナリ表に格納されずに、保留中の表に格納されるため、統計を公開前にテストできます。これらの保留中の統計を、個々のセッションに対して有効にするか制御できるので 、 統 計 を 公 開 前 に 検 証 で き ま す 。 統 計 収 集 の 保 留 を 有 効 に す る に は 、 い ず れ か のDBMS_STATS.SET_*_PREFS プロシージャを使用して、統計を保留するオブジェクトについてパラメータ PUBLISH の値を TRUE(デフォルト)から FALSE に変更する必要があります。

オブジェクトで統計を通常どおりに収集します。

BEGIN DBMS_STATS.RESTORE_TABLE_STATS(ownname

tabname => ‘SH’, => ‘SALES’,

as_of_timestamp => SYSTIMESTAMP-1 force => FALSE, no_invalidate => FALSE);

END; /

BEGIN DBMS_STATS.SET_TABLE_PREFS('SH', 'SALES', 'PUBLISH', 'FALSE');

END; /

BEGIN DBMS_STATS.GATHER_TABLE_STATS('SH', 'SALES');

END; /

Page 19: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

17 | Oracle Database 12c Release 2 のオプティマイザ統計について

これら のオブジェクトに対して収集された統計を表示するには、ディクショナリ・ビューUSER_*_PENDING_STATS を使用します。保留中の統計を使用するようにオプティマイザに指定する に は 、 ALTER SESSION コ マ ン ド を 実 行 し て 初 期 化 パ ラ メ ー タOPTIMIZER_USE_PENDING_STATS を TRUE に設定し、SQL ワークロードを実行します。ワークロードでアクセスされる表に保留中の統計が含まれていない場合、オプティマイザは標準のデータ・ディクショナリ表の現在の統計を使用します。保留中の統計の検証が済んだら、プロシージャDBMS_STATS.PUBLISH_PENDING_STATS を使用して保留中の統計を公開できます。

統計のエクスポートとインポート

統計はデータベース間でコピーできます。たとえば本番稼動前に、別の環境からコピーした統計を使 っ て 、 あ る 環 境 で パ フ ォ ー マ ン ス を テ ス ト す る と 有 益 な 場 合 が あ り ま す 。DBMS_STATS.EXPORT_*_STATS プロシージャと DBMS_STATS.IMPORT_*_STATS プロシージャを使用すると、データベース間で統計をコピーできます。

統計をエクスポートする前に、DBMS_STATS.CREATE_STAT_TABLE を使用して、統計を格納する表を作成する必要があります。表を作成したら、DBMS_STATS.EXPORT_*_STATS プロシージャを使用してデータ・ディクショナリから統計をエクスポートできます。統計を統計表に格納したら、データダンプを使用して本番データベースから統計表を抽出し、テスト・データベースにインポート で き ま す 。 統 計 表 を テ ス ト ・ シ ス テ ム に 正 し く イ ン ポ ー ト で き た ら 、DBMS_STATS.IMPORT_*_STATS プロシージャを使用して統計をデータ・ディクショナリにインポートできます。

パーティション統計のコピー

パーティション表を処理する際、SQL 文に適した実行計画を選択するために、オプティマイザは表全体の統計(グローバル統計)と個々のパーティションの統計(パーティション統計)の両方を使用します。問合せで単一パーティションにのみアクセスする場合、オプティマイザはアクセス対象のパーティションの統計のみ使用します。問合せで複数のパーティションにアクセスする場合は、グローバル統計を使用します。

レンジ・パーティション表では、新しいパーティションを既存の表に追加して、そのパーティションにのみ行を挿入するというのがごく一般的です。エンドユーザーが新しく挿入されたデータの問合せを統計の収集前に開始すると、統計が古いために、最適でない実行計画を取得する可能性があります。もっとも一般的なケースの 1 つは、where 句の条件に指定されている値が、列統計情報の最大値と最小値で表される値の範囲外である場合に発生します。これは、'out-of-range'エラーと呼ばれています。この場合、オプティマイザは条件の値と最大値の差分に基づいて選択性を割り当てます(値が最大値よりも大きいと仮定した場合)。つまり、値が最大値または最小値から離れているほど、選択性は少なくなります。

DBMS_STATS.COPY_TABLE_STATS プロシージャを使用すると、"out-of- range"状態になるのを防止できます。このプロシージャは、代表的なソース(サブ)パーティションの統計を、新しく作成された空の宛先(サブ)パーティションにコピーします。また、依存オブジェクト、列、ローカル(パーティション)索引などの統計もコピーします。パーティション列の最大値と最小値は次のように調整されます。

BEGIN DBMS_STATS.PUBLISH_PENDING_STATS('SH', 'SALES');

END; /

Page 20: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

18 | Oracle Database 12c Release 2 のオプティマイザ統計について

» パーティション・タイプが HASH の場合、宛先パーティションの最大値と最小値はソース・パーティションと同じになります。

» パーティション・タイプが LIST で、宛先パーティションが NOT DEFAULT パーティションである場合、宛先パーティションの最小値は、宛先パーティションを表す値リストの最小値に設定されます。宛先パーティションの最大値は、宛先パーティションを表す値リストの最大値に設定されます。

» パーティション・タイプが LIST で、宛先パーティションが DEFAULT パーティションである場合、宛先パーティションの最小値はソース・パーティションの最小値に設定されます。宛先パーティションの最大値は、ソース・パーティションの最大値に設定されます。

» パーティション・タイプが RANGE の場合、宛先パーティションの上限が MAXVALUE である場合を除き、宛先パーティションの最小値は前のパーティションの上限に設定され、宛先パーティションの最大値は宛先パーティションの上限に設定されます。宛先パーティションの上限がMAXVALUE である場合は、宛先パーティションの最大値は前のパーティションの上限に設定されます。

また、指定の scale_factor に基づいて、統計(ブロック数、行数など)を拡張できます。平均的な行の長さや個別値の数などの統計は調整されず、宛先パーティションで同じとみなされます。

次のコマンドは、SALES 表の SALES_Q3_2011 レンジ・パーティションの統計を SALES_Q4_2011パーティションにコピーし、基本統計を係数 2 で拡大します。

索引統計は、索引パーティションの名前が表パーティションの名前と同じ場合のみコピーされます(これがデフォルト)。グローバル・レベルの統計と表レベルの統計は、デフォルトでは更新されません。グローバル・レベルの統計が DBMS_STATS.COPY_TABLE_STATS プロシージャの影響を受けるのは、グローバル・レベルでは統計が存在せず、集計によってグローバル統計が生成される場合だけです。

BEGIN DBMS_STATS.COPY_TABLE_STATS('SH','SALES','SALES_Q3_2002','SALES_Q

4_2002', 2); END; /

Page 21: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

19 | Oracle Database 12c Release 2 のオプティマイザ統計について

統計の比較

実行計画がシステムごとに異なる場合があるおもな理由の 1 つとして、オプティマイザ統計がシステムごとに異なることが挙げられます。たとえば、データが同期されていない場合、テスト環境の統 計 は 本 番 環 境 に 比 べ て 異 な る 場 合 が あ り ま す 。 統 計 の 相 違 を 特 定 す る 場 合 は 、DBMS_STATS.DIFF_TABLE_STATS_*関数を使って、2 つの異なるソース(指定のソース"A"とソース"B")の統計を比較できます。たとえば、スキーマ 1 の表をスキーマ 2 の表と比較できます。また、2 つの異なる時点における個々の表の統計を比較したり、現在の統計と保留中の統計を比較したりすることも可能です。たとえば、現在の統計を昨日の統計と比較する場合を見てみます。

図17:ある日とその翌日のCUSTOMERSの統計の比較

あるデータベースの APP1.CUSTOMERS と別のデータベースの APP1.CUSTOMERS を比較する場合は、次のようになります。

システム 1:

システム 1 から APP1STAT 表をエクスポートし、システム 2 にインポートしてから、システム 2 で以下を実行します。

select report, maxdiffpct

from dbms_stats.diff_table_stats_in_history(user, 'CUSTOMERS', SYSDATE-1, SYSDATE, 2);

exec dbms_stats.create_stat_table('APP1','APP1STAT') exec dbms_stats.export_table_stats('APP1','CUSTOMERS',stattab=>'APP1STAT',statid=> 'mystats1')

select report from dbms_stats.diff_table_stats_in_stattab('APP1',

'CUSTOMERS', 'APP1STAT', NULL, 1, 'mystats1');

Page 22: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

20 | Oracle Database 12c Release 2 のオプティマイザ統計について

また、"DIFF"関数は、依存オブジェクト(索引、列、パーティション)の統計を比較し、これらの統計の差分が指定のしきい値を超える場合は、両方のソースのオブジェクトのすべての統計を表示します。しきい値は引数として関数に指定できます。デフォルト値は 10%です。最初のソースに対応する統計は、差分の割合を計算するための基礎として使用されます。

統計のロック

統計をロックして、表またはスキーマで新しい統計が収集されないようにすることが必要になる場合があります。統計をロックすると、統計のロックを解除するまで、または GATHER_*_STATS プロシージャの FORCE パラメータを TRUE に設定している場合を除き、ロックした統計を変更できません。

図18:表統計のロックとロック解除

統計のロックとロック解除は、表レベルまたはパーティション・レベルで行えます。

BEGIN DBMS_STATS.LOCK_PARTITION_STATS('SH', 'SALES', 'SALES_Q3_2000');

END;

Page 23: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

21 | Oracle Database 12c Release 2 のオプティマイザ統計について

ロックされた統計に階層が存在することに注意してください。たとえば、あるパーティション表の統計をロック後、1 つのパーティションで統計を再収集するために、そのパーティションのみ統計をロック解除すると、エラーORA-20005 が発生して再収集が失敗します。エラーが発生するのは、パーティションはロック解除されましたが、表レベル・ロックが引き続き適用されているためです。パーティションの統計収集は、FORCE パラメータを TRUE に設定している場合のみ成功します。

図19:ロックされた統計の階層。表レベル・ロックがパーティション・レベル・ロック解除よりも優先される

統計の手動設定

ごくまれな状況で、オプティマイザ統計をデータ・ディクショナリに手動で設定すると有益な場合があります。このような例として、頻繁に変更されるグローバル一時表が挙げられます(このホワイト・ペーパーでは統計の手動設定を説明していますが、統計の精度や一貫性が低くなり、パフォーマンスの低い実行計画となる可能性があるため、統計の手動設定は通常推奨されません)。統計を手動で設定するには、DBMS_STATS.SET_*_STATS プロシージャを使用します。

Page 24: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

22 | Oracle Database 12c Release 2 のオプティマイザ統計について

その他のタイプの統計

文の実行計画を決定するために、オプティマイザは基本的な表統計、列統計、索引統計だけでなく、その他の情報も使用します。その他の情報は、動的サンプリングやシステム統計の形式で取得されます。

動的統計(以前の動的サンプリング)

動的サンプリングは、SQL 文の最適化時に文固有の追加のオブジェクト統計を収集します。よくある誤解として、動的サンプリングをオプティマイザ統計の置換えとして使用できるというものがあります。動的サンプリングの目的は、既存の統計を補強することです。動的サンプリングは、高品質のカーディナリティ見積りを取得するには通常の統計では不十分な場合に使用されます。

Oracle Database 12c では、動的サンプリングが強化されて動的統計となっています。動的統計により、単一表のアクセスだけでなく、結合や group-by 条件の場合でもさらに精度の高いカーディナリティ見積りを取得するように、オプティマイザで既存の統計を補強できます。

それでは、動的統計はいつ、どのように使用されるのでしょうか。SQL 文のコンパイル時に、オプティマイザは、使用可能な統計が高品質の実行計画を生成するために十分か検討することで、動的統計を使用するかどうかを判断します。使用可能な統計が十分でない場合は、既存の統計情報に加えて動的サンプリングが使用されます。動的サンプリングは通常、非常に品質の低い計画が生成されないように、欠落しているか不足している統計を補うために使用されます。問合せの 1 つまたは複数の表に統計が含まれていない場合、SQL 文を最適化する前にこれらの表の基本統計を収集するために、オプティマイザによって動的統計が使用されます。この場合に収集される統計は、DBMS_STATS パッケージを使って収集される統計ほど高品質ではなく、完全ではありません。このトレードオフは、文のコンパイル時間への影響を限定するために行われます。

場合によっては、オプティマイザで動的統計をより"アグレッシブ"に使用する必要があります。たとえば、文に複雑な条件式が含まれていて、拡張統計が提供されていないか使用できない場合には、動的統計を使用する必要があるかもしれません。たとえば、相関付けられた 2 つの列に対し、非等価の where 句の条件が含まれた問合せがあるとします。標準的な統計では不十分であり、拡張統計は使用できません(非等価の条件であるため)。次のような SALES 表に対する単純な問合せでは、オプティマイザは、where 句の各条件のために問合せで返される行の数が減るとみなし、標準の統計に基づいてカーディナリティを 20,197 と判断します。実際には、返される行の数は 10 倍の210,420 となります。

図20:動的サンプリングを使用しない場合の、複雑な条件の実行計画

SELECT count(*) FROM sh.sales WHERE cust_id < 2222 AND prod_id > 5;

Page 25: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

23 | Oracle Database 12c Release 2 のオプティマイザ統計について

標準の統計では、オプティマイザはSALES表のCUST_IDとPROD_IDの相関関係を認識しません。OPTIMIZER_DYNAMIC_SAMPLING をレベル 6 に設定すると、オプティマイザは動的統計を使用して複雑な条件式に関する追加情報を収集します。動的統計で収集される追加情報により、オプティマイザはさらに精度の高いカーディナリティ見積りを生成できるため、よりパフォーマンスの高い実行計画が得られます。

図21:動的サンプリング・レベル6を使用した場合の、複雑な条件の実行計画

動 的 サ ン プ リ ン グ は 、 さ ま ざ ま な レ ベ ル ( 0 ~ 11 ) に 設 定 可 能 な パ ラ メ ー タOPTIMIZER_DYNAMIC_SAMPLING で制御します。これらのレベルによって、動的統計をいつ実行するかと、統計の収集にどの程度のサンプル・サイズを使用するかという、2 つの重要な側面を制御します。サンプル・サイズが大きいほど、動的サンプリングが問合せのコンパイル時間に与える影響が大きくなります。

11 に設定すると、オプティマイザは、動的統計が有益かどうか、どのくらいの量のデータをサンプリングするかを自動的に判断します。オプティマイザでは、使用されている条件の複雑さ、既存の基本統計、および SQL 文に想定される総実行時間に基づいて、動的統計を使用するかどうかを判断します。たとえば、動的統計は、オプティマイザが以前に不確定要素を扱った場合に実行されます。LIKE 条件とワイルドカードを使って問合せを行った場合などです。

図22:OPTIMIZER_DYNAMIC_SAMPLINGをレベル11に設定すると、不確定要素を扱う代わりに動的サンプリングを使用

Page 26: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

24 | Oracle Database 12c Release 2 のオプティマイザ統計について

これらの条件から、レベル 11 に設定すると、動的サンプリングが以前よりも高い頻度で実行される可能性があります。その場合、SQL 文の解析時間が長くなります。パフォーマンスへの影響を最小限に抑えるために、動的サンプリング問合せの結果は、Oracle Database 12c Release 1 ではサーバー結果キャッシュに、Oracle Database 12c Release 2 以降は(代わりに)SQL 計画ディレクティブ・リポジトリに保持されます。これにより、動的サンプリング問合せで収集された統計を他の SQL 文で 共 有 で き ま す 。 保 持 さ れ た 動 的 サ ン プ リ ン グ の 結 果 は 、 デ ー タ ベ ー ス ・ ビ ュ ーDBA_SQL_PLAN_DIRECTIVES で確認できます。TYPE 列の値は DYNAMIC_SAMPLING_RESULT となっています(Oracle Database 12c Release 2 以降)。

OPTIMIZER_DYNAMIC_SAMPLING が 11 に設定されていなくても、適応動的サンプリング(つまり、レベル 11 式の動的サンプリング)を解析時に開始できます。大きい表に対するパラレル問合せ、および関連する DYNAMIC_SAMPLING SQL 計画ディレクティブのあるシリアル問合せの場合などです。この動作が実行されるのは、データベース・パラメータ OPTIMIZER_DYNAMIC_STATISTICS

が TRUE に設定されている場合です(デフォルトは FALSE)。

システム統計

システム統計により、文を実行する実際のシステム・ハードウェアの情報(CPU 速度や IO パフォーマンスなど)を使用することで、オプティマイザは実行計画の各操作の見積りをより正確に行うことができます。

システム統計はデフォルトで有効になっており、デフォルト値で自動的に初期化されます。これらのデフォルト値はほとんどのシステム(Oracle Exadata を含む)に対応する値になっているため、通常、システム統計を手動で収集する必要はありません。ただし、システム統計は、自動統計収集ジョブによる自動収集の対象ではありません。

システム統計を手動で収集する場合は、デフォルト値が上書きされ、Oracle Optimizer によるコスト計算が影響を受けます。その結果、SQL 実行計画が変更される可能性があるため、本番システムで変更を実装する前にそれが有効か評価することが重要です。

シ ス テ ム 統 計 を 収 集 す る た め に 、 代 表 的 な ワ ー ク ロ ー ド 時 間 枠 でDBMS_STATS.GATHER_SYSTEM_STATS を使用できます。ピーク・ワークロード時に使用するのが理想的です。また、Exadata システム上の Oracle Database には Exadata 固有のオプションがあります。

ディクショナリ表の統計

現在、コストベース・オプティマイザはサポートされている唯一のオプティマイザであるため、すべてのディクショナリ表('SYS'、SYSTEM などが所有し、SYSTEM 表領域や SYSAUX 表領域に格納されている表)を含め、データベースのすべての表で統計が必要です。ディクショナリ表の統計は、夜間のメンテナンス時間枠時に実行される自動統計収集ジョブによってメンテナンスされます。おもなアプリケーション・スキーマに対して自動統計収集ジョブをオフにすることを選択する場合、ディクショナリ表に対しては引き続きオンにすることを検討します。これを行うには、プロシージャ DBMS_STATS.SET_GLOBAL_PREFS を使用して AUTOSTATS_TARGET の値を AUTO からORACLE に変更します。

EXEC DBMS_STATS.GATHER_SYSTEM_STATS('EXADATA')

Page 27: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

25 | Oracle Database 12c Release 2 のオプティマイザ統計について

DBMS_STATS.GATHER_DICTIONARY_STATS プロシージャを使用し、ディクショナリ表で統計を手動で収集できます。ディクショナリ統計を更新するには、ANALYZE ANY DICTIONARY システム権限と ANALYZE ANY システム権限の両方、または DBA ロールが必要です。ユーザー・スキーマと同様の方法で、ディクショナリ表の統計を定期的にメンテナンスすることを推奨します。

固定オブジェクトの統計

動的パフォーマンス表やその索引(固定オブジェクト)で統計を収集することも必要となります。これらは、V$ビュー(V$SQL など)が構築される X$表です。他のユーザー表やビューと同様に、V$ビューは SQL 文に表示されるため、オプティマイザで適切な実行計画を生成できるように、これらの表でオプティマイザ統計を収集することが重要です。ただし、他のデータベース表とは異なり、オプティマイザ統計が見つからない場合、X$表が関係している SQL 文に動的サンプリングは自動的には使用されません。統計が見つからない場合、オプティマイザは事前定義のデフォルト値を統計に使用します。これらのデフォルト値は代表的な値ではないため、実行計画が最適化されずに、システムで重大なパフォーマンスの問題が発生する可能性があります。固定オブジェクトの統計の収集を推奨しているのは、このためです。

Oracle Database 12c 以前では、固定オブジェクトの統計は、自動統計収集ジョブでは収集またはメンテナンスされません。DBMS_STATS.GATHER_FIXED_OBJECTS_STATS プロシージャを使用して、固定オブジェクトの統計を手動で収集できます。

Oracle Database 12c 以降、固定表の統計がない場合は、自動統計収集ジョブによって収集されます。それでも、代表的なワークロードがいったん実行されたら、これらを手動で収集することを推奨します。

DBMS_STATS.GATHER_FIXED_OBJECTS_STATS プ ロ シ ー ジ ャ は 、 ブ ロ ッ ク 数 を 除 き 、DBMS_STATS.GATHER_TABLE_STATS と同じ統計を収集します。x$表はメモリ構造にのみ保存され、ディスクには保存されないため、ブロックは常に 0 に設定されます。x$表は本質的に一時的なものであるため、システムに代表的なワークロードが存在する時に固定オブジェクトの統計を収集することが重要です。固定オブジェクトの統計を更新するには、ANALYZE ANY DICTIONARY システム権限または DBA ロールが必要です。主要なデータベースやアプリケーションのアップグレードを行う場合は、固定オブジェクトの統計を再収集することを推奨します。

GATHER_FIXED_OBJECTS_STATS を実行していても、一部の固定表には統計がありません。表の一部はパフォーマンス上の理由から明示的にスキップされるため、これは想定内の動作です。

式の統計

Oracle Database 12c Release 2 以降、オプティマイザの式追跡機能により、データベース・ワークロードに現れる式の統計がキャプチャされ、この情報はデータ・ディクショナリに保持されます。このデータは Oracle Optimizer によって保持され、Oracle Database In-Memory のインメモリー式(IME)機能によって使用されます。

BEGIN DBMS_STATS.SET_GLOBAL_PREFS('AUTOSTATS_TARGET','ORACLE'); END; /

BEGIN DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;

END; /

Page 28: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

26 | Oracle Database 12c Release 2 のオプティマイザ統計について

図 23 に、統計がどのように表示されるかを示します。列の使用状況と式の使用状況がどのように追跡されているかに注目してください。

図23:式の統計の表示

統計は 15 分ごとに自動的に更新されますが、データは(上述のとおりに)手動でフラッシュできます。評価カウントは推定値であり、同様に固定コストも、式の実行で生じるコストの推定値です。集計式(SUM や MAX など)は追跡されず、複数の表からの列を含む式も追跡されません。

LATEST スナップショットは、キャプチャされた最新の一連の統計で、CUMULATIVE は長期的な累積値です。

Page 29: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

27 | Oracle Database 12c Release 2 のオプティマイザ統計について

結論

コストベース・オプティマイザが実行計画のコストを正確に判断するためには、SQL 文でアクセスするすべてのオブジェクト(表と索引)に関する情報と、SQL 文を実行するシステムに関する情報をオプティマイザが利用できる必要があります。必要となるこの情報は一般に、オプティマイザ統計と呼ばれます。統計を理解して管理することが、最適な SQL 実行に重要です。統計を収集するタイミングや、統計を適切なタイミングで収集する方法を把握することは、適切なパフォーマンスを維持するために重要です。

Oracle Database によって維持される統計のタイプを学んだので、今度は『Best Practices for Gathering Optimizer Statistics with Oracle Database 12c Release 2』を読むことを検討してください。このホワイト・ペーパーでは、最小限の管理オーバーヘッドであらゆるタイプの統計を効果的に維持する方法について説明します。

Page 30: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

28 | Oracle Database 12c Release 2 のオプティマイザ統計について

参考資料

1. Oracle ホワイト・ペーパー:『Best Practices for Gathering Optimizer Statistics with Oracle Database 12c Release 2』

2. Oracle ホワイト・ペーパー:『Oracle Database 12c Release 2 のオプティマイザ』

Page 31: Oracle Database 12c Release 2のオプティマイザ統計...SQL実行の達成に極めて重要です。このホワイト・ペーパーは、 オプティマイザ統計に関する2部構成シリーズの1部目となっており、統計の重要な概念、

Oracle Corporation, World Headquarters

500 Oracle Parkway

Redwood Shores, CA 94065, USA

海外からのお問い合わせ窓口

電話:+1.650.506.7000

ファクシミリ:+1.650.506.7200

C O N N E C T W I T H U S

blogs.oracle.com/oracle

facebook.com/oracle

twitter.com/oracle

oracle.com

Copyright © 2014, Oracle and/or its affiliates.All rights reserved.本文書は情報提供のみを目的として提供されており、ここに記載される内容は予告なく変更されることがあります。本文書は、その内容に誤りがないことを保証するものではなく、また、口頭による明示的保証や法律による黙示的保証を含め、商品性ないし特定目的適合性に関する黙示的保証および条件などのいかなる保証および条件も提供するものではありません。オラクルは本文書に関するいかなる法的責任も明確に否認し、本文書によって直接的または間接的に確立される契約義務はないものとします。本文書はオラクルの書面による許可を前もって得ることなく、いかなる目的のためにも、電子または印刷を含むいかなる形式や手段によっても再作成または送信することはできません。 Oracle および Java は Oracle およびその子会社、関連会社の登録商標です。その他の名称はそれぞれの会社の商標です。Intel および Intel Xeon は Intel Corporation の商標または登録商標です。すべての SPARC 商標はライセンスに基づいて使用される SPARC International, Inc.の商標または登録商標です。AMD、Opteron、AMD ロゴおよび AMD Opteron ロゴは、Advanced Micro Devicesの商標または登録商標です。UNIX は、The Open Group の登録商標です。0317