11 ヒストグラム
ヒストグラムは、表の列のデータ分布に関する詳細な情報を提供する特殊なタイプの列統計です。ヒストグラムでは、コインをバケツに分けるように、値をバケットに分類します。
NDVおよびデータの分布に基づいて、作成するヒストグラムのタイプが選択されます。(場合によっては、ヒストグラムを作成する際、データベースで、内部的に事前定義された数の行がサンプリングされます。)ヒストグラムのタイプは次のとおりです。
-
頻度ヒストグラムおよび上位頻度ヒストグラム
-
高さ調整済ヒストグラム(レガシー)
-
ハイブリッド・ヒストグラム
この章のトピックは、次のとおりです:
11.1 ヒストグラムの目的
デフォルトでは、オプティマイザは、列内の個別値全体で行のデータ配分が均一であると想定します。
列にデータの偏りがある(列内のデータ配分が均一ではない)場合は、ヒストグラムを使用することにより、これらの列を含むフィルタ述語や結合述語に対してオプティマイザが正確なカーディナリティ予測を生成できるようになります。
たとえば、カリフォルニアに拠点を置く書籍店では、書籍の95%をカリフォルニアに、4%をオレゴンに、1%をネバダに出荷しています。書籍注文表には300,000行あります。表の列には、注文の出荷先の州が格納されています。ユーザーが、オレゴンに出荷された書籍の数を問い合せます。ヒストグラムを使用しない場合、オプティマイザは300000/3 (NDVは3)で均一に分布されていると想定し、カーディナリティを100,000行で見積ります。この見積りの場合、オプティマイザは全表スキャンを選択します。ヒストグラムがある場合、オプティマイザは、書籍の4%がオレゴンに出荷されていると計算し、索引スキャンを選択します。
関連トピック
11.2 ヒストグラムが作成される場合
DBMS_STATS
によって表の統計が収集され、問合せによってこの表の列が参照される場合、これまでの問合せのワークロードに従って、必要に応じて自動的にヒストグラムが作成されます。
基本的なプロセスは次のとおりです。
-
METHOD_OPT
パラメータにデフォルトのSIZE AUTO
が設定された状態で、表にDBMS_STATS
を実行します。 -
ユーザーが、この表に問合せを行います。
-
データベースにより前の問合せの述語が記録され、データ・ディクショナリ表
SYS.COL_USAGE$
が更新されます。 -
DBMS_STATS
を再度実行すると、DBMS_STATS
によりSYS.COL_USAGE$
に問い合され、前回の問合せのワークロードに基づいて、どの列にヒストグラムが必要かが決定されます。
AUTO
機能の結果には次のものが含まれます。
-
問合せが時間の経過とともに変更される場合、
DBMS_STATS
によって収集される統計の種類が変更される場合があります。たとえば、表のデータに変更がない場合でも、問合せとDBMS_STATS
の操作によって、これらの表を参照する問合せの計画が変更される場合があります。 -
表の統計を収集するが問合せは行わない場合、この表の列のヒストグラムは作成されません。データベースに自動でヒストグラムを作成させるには、1つ以上の問合せを実行して
SYS.COL_USAGE$
の列使用情報に移入する必要があります。
例11-1 ヒストグラムの自動作成
sh.sh_ext
は、sh.sales
表と同じ列を含む外部表だとします。新しい表sales2
を作成して、sh_ext
をソースとして使用するバルク・ロードを実行すると、自動的にsales2
の統計が作成されます。また、次のように索引を作成します。
SQL> CREATE TABLE sales2 AS SELECT * FROM sh_ext;
SQL> CREATE INDEX sh_12c_idx1 ON sales2(prod_id);
SQL> CREATE INDEX sh_12c_idx2 ON sales2(cust_id,time_id);
データ・ディクショナリに問い合せて、sales2
列のヒストグラムが存在するかどうか確認します。sales2
にはまだ問い合されていないため、ヒストグラムはまだ作成されていません。
SQL> SELECT COLUMN_NAME, NOTES, HISTOGRAM
2 FROM USER_TAB_COL_STATISTICS
3 WHERE TABLE_NAME = 'SALES2';
COLUMN_NAME NOTES HISTOGRAM
------------- -------------- ---------
AMOUNT_SOLD STATS_ON_LOAD NONE
QUANTITY_SOLD STATS_ON_LOAD NONE
PROMO_ID STATS_ON_LOAD NONE
CHANNEL_ID STATS_ON_LOAD NONE
TIME_ID STATS_ON_LOAD NONE
CUST_ID STATS_ON_LOAD NONE
PROD_ID STATS_ON_LOAD NONE
sales2
に製品42
の行数を問い合せた後、GATHER AUTO
オプションを使用して表統計を収集します。
SQL> SELECT COUNT(*) FROM sales2 WHERE prod_id = 42;
COUNT(*)
----------
12116
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'SALES2',OPTIONS=>'GATHER AUTO');
データ・ディクショナリに問い合せると、前回の問合せで収集された情報に基づいてprod_id
列のヒストグラムが作成されたことがわかります。
SQL> SELECT COLUMN_NAME, NOTES, HISTOGRAM
2 FROM USER_TAB_COL_STATISTICS
3 WHERE TABLE_NAME = 'SALES2';
COLUMN_NAME NOTES HISTOGRAM
------------- -------------- ---------
AMOUNT_SOLD STATS_ON_LOAD NONE
QUANTITY_SOLD STATS_ON_LOAD NONE
PROMO_ID STATS_ON_LOAD NONE
CHANNEL_ID STATS_ON_LOAD NONE
TIME_ID STATS_ON_LOAD NONE
CUST_ID STATS_ON_LOAD NONE
PROD_ID HISTOGRAM_ONLY FREQUENCY
関連トピック
11.3 Oracle Databaseによるヒストグラム・タイプの選択方法
Oracle Databaseでは、複数の基準を使用して、作成するヒストグラム(頻度、上位頻度、高さ調整済またはハイブリッド)を決定します。
ヒストグラム式では、次の変数が使用されます。
-
NDV
これは、列内の個別値の数を表します。たとえば、列に値
100
、200
および300
のみが含まれている場合、この列のNDVは3です。 -
n
この変数は、ヒストグラム・バケットの数を表します。デフォルトは254です。
-
p
この変数は、内部割合のしきい値を表し、(1–(1/n)) * 100と等しくなります。たとえば、n = 254の場合、pは99.6です。
追加の基準は、DBMS_STATS
統計収集プロシージャでestimate_percent
パラメータがAUTO_SAMPLE_SIZE
(デフォルト)に設定されているかどうかです。
次の図は、ヒストグラム作成のディシジョン・ツリーを示しています。
11.4 ヒストグラム使用時のカーディナリティ・アルゴリズム
ヒストグラムを使用する場合、カーディナリティのアルゴリズムは、エンドポイント番号やエンドポイント値、列値がポピュラーか非ポピュラーかなどの要因により異なります。
この項では、次の項目について説明します。
11.4.1 エンドポイント番号とエンドポイント値
エンドポイント番号は、バケットを一意に識別する数値です。頻度ヒストグラムおよびハイブリッド・ヒストグラムでは、エンドポイント番号は、現在および前のバケットに含まれるすべての値の頻度の累積になります。
たとえば、バケットのエンドポイント番号が100
の場合、現在およびすべての前のバケットの合計頻度は100です。高さ調整済ヒストグラムでは、オプティマイザはバケットの数を0
または1
から順に数えます。いずれの場合でも、エンドポイント番号はバケット番号になります。
エンドポイント値は、バケット内の値の範囲で最も高い値です。たとえば、バケットに含まれる値が52794
と52795
のみの場合、エンドポイント値は52795
です。
11.4.2 ポピュラー値と非ポピュラー値
ヒストグラムの値のポピュラリティは、カーディナリティ予測アルゴリズムに影響します。
具体的には、カーディナリティ予測に次のように影響します。
-
ポピュラー値
ポピュラー値は複数のバケットのエンドポイント値として出現します。オプティマイザは、値がポピュラー値かどうかを判断するために、まずその値がバケットのエンドポイント値かどうかを確認します。エンドポイント値の場合、頻度ヒストグラムでは、オプティマイザは現在のバケットのエンドポイント番号から前のバケットのエンドポイント番号を減算します。ハイブリッド・ヒストグラムでは、エンドポイントごとにすでにこの情報が個別に格納されています。この値が1よりも大きい場合、その値はポピュラーです。
オプティマイザは、次の式を使用してポピュラー値のカーディナリティ予測を計算します。
cardinality of popular value = (num of rows in table) * (num of endpoints spanned by this value / total num of endpoints)
-
非ポピュラー値
ポピュラーでない値は、非ポピュラー値です。オプティマイザは、次の式を使用して非ポピュラー値のカーディナリティ予測を計算します。
cardinality of nonpopular value = (num of rows in table) * density
オプティマイザは、バケット数やNDVなどの要因に基づいて内部アルゴリズムを使用し、密度を計算します。密度は、
0
から1
の間の小数値として表されます。値が1
に近いと、述語リストでこの列を参照する問合せによって多くの行が戻されることをオプティマイザが予測していることを示します。値が0
に近いと、少ない行が戻されることをオプティマイザが予測していることを示します。
関連項目:
DBA_TAB_COL_STATISTICS.DENSITY
列について学習するには、Oracle Databaseリファレンスを参照してください
11.4.3 バケットの圧縮
場合によっては、バケットの合計数を減らすために、オプティマイザが複数のバケットを1つのバケットに圧縮することがあります。
たとえば、次の頻度ヒストグラムは、最初のバケット番号が1
で、最後のバケット番号が23
であることを示しています。
ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
1 52792
6 52793
8 52794
9 52795
10 52796
12 52797
14 52798
23 52799
いくつかのバケットが欠落しています。当初は2
から6
の各バケットに、値52793
の単一のインスタンスが含まれていました。オプティマイザは、これらのバケットのすべてを最も高いエンドポイント番号(バケット6
)のバケットに圧縮しました。これにより、現在このバケットには値52793
のインスタンスが5個含まれています。現在のバケット(6
)と前のバケット(1
)とのエンドポイント番号の差が5であるため、この値はポピュラーです。このように、値52793
は、圧縮前は5個のバケットを使用するエンドポイントでした。
次の注釈は、圧縮されたバケットとポピュラー値を示しています。
ENDPOINT_NUMBER ENDPOINT_VALUE
--------------- --------------
1 52792 -> nonpopular
6 52793 -> buckets 2-6 compressed into 6; popular
8 52794 -> buckets 7-8 compressed into 8; popular
9 52795 -> nonpopular
10 52796 -> nonpopular
12 52797 -> buckets 11-12 compressed into 12; popular
14 52798 -> buckets 13-14 compressed into 14; popular
23 52799 -> buckets 15-23 compressed into 23; popular
11.5 頻度ヒストグラム
頻度ヒストグラムでは、列の各個別値がヒストグラムの1つのバケットに対応しています。各値には専用のバケットがあるため、多くの値を持つバケットもあり、ほとんど値がないバケットもあります。
頻度ヒストグラムをコインの分類に例えて考えるならば、個々のコインが最初は固有のバケットに入るようにすることです。たとえば、最初のペニーをバケット1に、2番目のペニーはバケット2に、最初のニッケルはバケット3に入れるなどのようにします。続いて、すべてのペニーを1つのペニーのバケットにまとめ、すべてのニッケルを1つのニッケルのバケットにまとめます。残りのコインについても同様に行います。
この項では、次の項目について説明します。
11.5.1 頻度ヒストグラムの基準
頻度ヒストグラムは、要求されたヒストグラム・バケットの数に依存します。
「Oracle Databaseによるヒストグラム・タイプの選択方法」の論理図に示すように、次の基準を満たす場合に、データベースは頻度ヒストグラムを作成します。
-
NDVがn以下である(nはヒストグラム・バケットの数(デフォルトは
254
)です)。たとえば、
sh.countries.country_subregion_id
列には、52792
から52799
までの範囲で順番に8個の個別値があります。nがデフォルトの254
である場合、8 <= 254
であるため、オプティマイザは頻度ヒストグラムを作成します。 -
DBMS_STATS
統計収集プロシージャのestimate_percent
パラメータが、ユーザー指定の値またはAUTO_SAMPLE_SIZE
に設定されている。
Oracle Database 12cからは、サンプリング・サイズがデフォルトのAUTO_SAMPLE_SIZE
である場合、全表スキャンによって頻度ヒストグラムが作成されます。他のすべてのサンプリング率の指定では、データベースは、サンプルから頻度ヒストグラムを導出します。Oracle Database 12cより前のリリースでは、データベースは、小規模なサンプルに基づいてヒストグラムを収集していました。これは、頻度の低い値は多くの場合、サンプルに出現しないことを意味します。このような場合、密度を使用すると、オプティマイザが選択性を過大に見積ることがありました。
関連項目:
AUTO_SAMPLE_SIZE
について学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
11.5.2 頻度ヒストグラムの生成
このシナリオでは、サンプル・スキーマを使用して、頻度ヒストグラムを生成する方法を説明します。
前提条件
このシナリオでは、sh.countries.country_subregion_id
列に頻度ヒストグラムを生成することを想定しています。この表には23行が含まれています。
次の問合せは、country_subregion_id
列には分布が均一ではない8個の個別値が含まれていることを示しています(出力例も示します)。
SELECT country_subregion_id, count(*)
FROM sh.countries
GROUP BY country_subregion_id
ORDER BY 1;
COUNTRY_SUBREGION_ID COUNT(*)
-------------------- ----------
52792 1
52793 5
52794 2
52795 1
52796 1
52797 2
52798 2
52799 9
頻度ヒストグラムを生成するには:
-
バケット数はデフォルトの254のままで、
sh.countries
およびcountry_subregion_id
列の統計を収集します。たとえば、次のPL/SQL無名ブロックを実行します。
BEGIN DBMS_STATS.GATHER_TABLE_STATS ( ownname => 'SH' , tabname => 'COUNTRIES' , method_opt => 'FOR COLUMNS COUNTRY_SUBREGION_ID' ); END;
-
country_subregion_id
列のヒストグラム情報を問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT TABLE_NAME, COLUMN_NAME, NUM_DISTINCT, HISTOGRAM FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME='COUNTRIES' AND COLUMN_NAME='COUNTRY_SUBREGION_ID'; TABLE_NAME COLUMN_NAME NUM_DISTINCT HISTOGRAM ---------- -------------------- ------------ --------------- COUNTRIES COUNTRY_SUBREGION_ID 8 FREQUENCY
列の個別値がn以下(nはデフォルトの
254
)であるため、オプティマイザは頻度ヒストグラムを選択します。 -
country_subregion_id
列のエンドポイント番号とエンドポイント値を問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT ENDPOINT_NUMBER, ENDPOINT_VALUE FROM USER_HISTOGRAMS WHERE TABLE_NAME='COUNTRIES' AND COLUMN_NAME='COUNTRY_SUBREGION_ID'; ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 1 52792 6 52793 8 52794 9 52795 10 52796 12 52797 14 52798 23 52799
図11-2に、ヒストグラムの8個のバケットを図示します。それぞれの値は、バケットに入るコインとして表されています。
図11-2に示したように、それぞれの個別値には固有のバケットがあります。これは頻度ヒストグラムであるため、エンドポイント番号はエンドポイントの頻度の累積です。
52793
の場合、エンドポイント番号6
は、この値が5回(6 - 1)出現することを示しています。52794
の場合、エンドポイント番号8
は、この値が2回(8 - 6)出現することを示しています。エンドポイントが2以上で、前のエンドポイントよりも大きいバケットにはすべて、ポピュラー値が含まれます。したがって、バケット
6
、8
、12
、14
および23
にはポピュラー値が含まれます。オプティマイザは、エンドポイント番号に基づいてそれらのカーディナリティを計算します。たとえば、オプティマイザは次の式を使用して、値52799
のカーディナリティ(C
)を計算します。この場合、表内の行数は23です。C = 23 * ( 9 / 23 )
バケット
1
、9
および10
には非ポピュラー値が含まれます。オプティマイザは、それらのカーディナリティを密度に基づいて見積ります。
関連項目:
-
DBMS_STATS.GATHER_TABLE_STATS
プロシージャについて学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。 -
USER_TAB_COL_STATISTICS
ビューについて学習するには、Oracle Databaseリファレンスを参照してください -
USER_HISTOGRAMS
ビューについて学習するには、Oracle Databaseリファレンスを参照してください
11.6 上位頻度ヒストグラム
上位頻度ヒストグラムは頻度ヒストグラムのバリエーションで、統計上重要ではない非ポピュラー値を無視する頻度ヒストグラムです。
たとえば、1000枚のコインの山にペニーが1枚しか含まれていない場合、コインをバケットに分類する際に、このペニーは無視できます。上位頻度ヒストグラムでは、高ポピュラー値に対してより適切なヒストグラムを生成できます。
この項では、次の項目について説明します。
11.6.1 上位頻度ヒストグラムの基準
低い数値が行のほとんどを占める場合、この低い値のセットに頻度ヒストグラムを作成すると効果的です。これは、NDVが要求されたヒストグラム・バケットの数よりも大きい場合でも同様です。頻繁に出現する値に関するより高品質なヒストグラムを作成するために、オプティマイザは、非ポピュラー値を無視し、上位頻度ヒストグラムを作成します。
「Oracle Databaseによるヒストグラム・タイプの選択方法」の論理図に示すように、次の基準を満たす場合に、データベースは上位頻度ヒストグラムを作成します。
-
NDVがnより大きい(nはヒストグラム・バケットの数(デフォルトは
254
)です)。 -
上位nの頻出値によって占められている行の割合がしきい値p以上である。ここで、pは
(1-(1/
n
))*100
です。 -
DBMS_STATS
統計収集プロシージャのestimate_percent
パラメータがAUTO_SAMPLE_SIZE
に設定されている。
関連項目:
AUTO_SAMPLE_SIZE
について学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
11.6.2 上位頻度ヒストグラムの生成
このシナリオでは、サンプル・スキーマを使用して、上位頻度ヒストグラムを生成する方法を説明します。
前提条件
このシナリオでは、sh.countries.country_subregion_id
列に上位頻度ヒストグラムを生成することを想定しています。この表には23行が含まれています。
次の問合せは、country_subregion_id
列には分布が均一ではない8個の個別値が含まれていることを示しています(出力例も示します)。
SELECT country_subregion_id, count(*)
FROM sh.countries
GROUP BY country_subregion_id
ORDER BY 1;
COUNTRY_SUBREGION_ID COUNT(*)
-------------------- ----------
52792 1
52793 5
52794 2
52795 1
52796 1
52797 2
52798 2
52799 9
上位頻度ヒストグラムを生成するには:
-
個別値よりも少ないバケット数を指定して、
sh.countries
およびcountry_subregion_id
列の統計を収集します。たとえば、次のコマンドを入力して7個のバケットを指定します。
BEGIN DBMS_STATS.GATHER_TABLE_STATS ( ownname => 'SH' , tabname => 'COUNTRIES' , method_opt => 'FOR COLUMNS COUNTRY_SUBREGION_ID SIZE 7' ); END;
-
country_subregion_id
列のヒストグラム情報を問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT TABLE_NAME, COLUMN_NAME, NUM_DISTINCT, HISTOGRAM FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME='COUNTRIES' AND COLUMN_NAME='COUNTRY_SUBREGION_ID'; TABLE_NAME COLUMN_NAME NUM_DISTINCT HISTOGRAM ---------- -------------------- ------------ --------------- COUNTRIES COUNTRY_SUBREGION_ID 7 TOP-FREQUENCY
sh.countries.country_subregion_id
列には8個の個別値が含まれますが、ヒストグラムには7個のバケットのみが含まれ、n=7
となります。この場合は、上位頻度ヒストグラムまたはハイブリッド・ヒストグラムのみが作成されます。country_subregion_id
列では、上位7個の最頻出値が行数の95.6%を占めています。これは、しきい値である85.7%を上回っているため、上位頻度ヒストグラムが生成されます。 -
この列のエンドポイント番号とエンドポイント値を問い合せます。
たとえば、次の問合せを使用します(出力例も示します)。
SELECT ENDPOINT_NUMBER, ENDPOINT_VALUE FROM USER_HISTOGRAMS WHERE TABLE_NAME='COUNTRIES' AND COLUMN_NAME='COUNTRY_SUBREGION_ID'; ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 1 52792 6 52793 8 52794 9 52796 11 52797 13 52798 22 52799
図11-3に、上位頻度ヒストグラムの7個のバケットを図示します。この図では、値はコインとして表されています。
図11-3で示したように、それぞれの個別値には固有のバケットがあります。ただし
52795
は例外です。この値は非ポピュラー値であり、統計上重要ではないため、ヒストグラムから除外されます。通常の頻度ヒストグラムの場合と同様に、エンドポイント番号は値の頻度の累積になります。
関連項目:
-
DBMS_STATS.GATHER_TABLE_STATS
プロシージャについて学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。 -
USER_TAB_COL_STATISTICS
ビューについて学習するには、Oracle Databaseリファレンスを参照してください -
USER_HISTOGRAMS
ビューについて学習するには、Oracle Databaseリファレンスを参照してください
11.7 高さ調整済ヒストグラム(レガシー)
レガシーの高さ調整済ヒストグラムでは、列値がバケットに分割され、各バケットにほぼ同数の行が存在します。
たとえば、99枚のコインを4つのバケットに分配する場合、それぞれのバケットに入るコインの枚数はおよそ25枚です。ヒストグラムは、値範囲でのエンドポイントの位置を示します。
この項では、次の項目について説明します。
11.7.1 高さ調整済ヒストグラムの基準
Oracle Database 12cより前は、NDVがnを超えた場合に、高さ調整済ヒストグラムが作成されていました。このタイプのヒストグラムは、範囲述語、および少なくとも2つのバケットでエンドポイントとして出現する値の等価述語に対して有用でした。
「Oracle Databaseによるヒストグラム・タイプの選択方法」の論理図に示すように、次の基準を満たす場合に、データベースは高さ調整済ヒストグラムを作成します。
-
NDVがnより大きい(nはヒストグラム・バケットの数(デフォルトは
254
)です)。 -
DBMS_STATS
統計収集プロシージャのestimate_percent
パラメータがAUTO_SAMPLE_SIZE
に設定されていない。
したがって、Oracle Database 12cで新しいヒストグラムが作成される場合、サンプリング率がAUTO_SAMPLE_SIZE
に設定されていると、作成されるヒストグラムは、上位頻度ヒストグラムかハイブリッド・ヒストグラムのいずれかであり、高さ調整済ヒストグラムではないということになります。
Oracle Database 11gをOracle Database 12cにアップグレードした場合、アップグレード前に作成された高さ調整済ヒストグラムは引き続き使用されます。ただし、ヒストグラムを作成した表の統計をリフレッシュすると、データベースはこの表に関する既存の高さ調整済ヒストグラムを置き換えます。置換ヒストグラムのタイプは、NDVおよび次の条件の両方に依存します。
-
サンプリング率が
AUTO_SAMPLE_SIZE
の場合、データベースではハイブリッド・ヒストグラムまたは頻度ヒストグラムのいずれかが作成されます。 -
サンプリング率が
AUTO_SAMPLE_SIZE
でない場合、データベースでは高さ調整済ヒストグラムまたは頻度ヒストグラムのいずれかが作成されます。
11.7.2 高さ調整済ヒストグラムの生成
このシナリオでは、サンプル・スキーマを使用して、高さ調整済ヒストグラムを生成する方法を説明します。
前提条件
このシナリオでは、sh.countries.country_subregion_id
列に高さ調整済ヒストグラムを生成することを想定しています。この表には23行が含まれています。
次の問合せは、country_subregion_id
列には分布が均一ではない8個の個別値が含まれていることを示しています(出力例も示します)。
SELECT country_subregion_id, count(*) FROM sh.countries GROUP BY country_subregion_id ORDER BY 1; COUNTRY_SUBREGION_ID COUNT(*) -------------------- ---------- 52792 1 52793 5 52794 2 52795 1 52796 1 52797 2 52798 2 52799 9
高さ調整済ヒストグラムを生成するには:
-
個別値よりも少ないバケット数を指定して、
sh.countries
およびcountry_subregion_id
列の統計を収集します。ノート:
高さ調整済ヒストグラムの作成に必要なOracle Database 11gの動作をシミュレートするには、
estimate_percent
をデフォルト以外の値に設定します。デフォルト以外の値を指定すると、頻度ヒストグラムまたは高さ調整済ヒストグラムが作成されます。たとえば、次のコマンドを入力します。
BEGIN DBMS_STATS.GATHER_TABLE_STATS ( ownname => 'SH' , tabname => 'COUNTRIES' , method_opt => 'FOR COLUMNS COUNTRY_SUBREGION_ID SIZE 7' , estimate_percent => 100 ); END;
-
country_subregion_id
列のヒストグラム情報を問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT TABLE_NAME, COLUMN_NAME, NUM_DISTINCT, HISTOGRAM FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME='COUNTRIES' AND COLUMN_NAME='COUNTRY_SUBREGION_ID'; TABLE_NAME COLUMN_NAME NUM_DISTINCT HISTOGRAM ---------- -------------------- ------------ --------------- COUNTRIES COUNTRY_SUBREGION_ID 8 HEIGHT BALANCED
個別値の数(8)がバケット数(7)よりも大きく、
estimate_percent
値がデフォルト以外であるため、オプティマイザは高さ調整済ヒストグラムを選択します。 -
各個別値が占める行数を問い合せます。
たとえば、次の問合せを使用します(出力例も示します)。
SELECT COUNT(country_subregion_id) AS NUM_OF_ROWS, country_subregion_id FROM countries GROUP BY country_subregion_id ORDER BY 2; NUM_OF_ROWS COUNTRY_SUBREGION_ID ----------- -------------------- 1 52792 5 52793 2 52794 1 52795 1 52796 2 52797 2 52798 9 52799
-
country_subregion_id
列のエンドポイント番号とエンドポイント値を問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT ENDPOINT_NUMBER, ENDPOINT_VALUE FROM USER_HISTOGRAMS WHERE TABLE_NAME='COUNTRIES' AND COLUMN_NAME='COUNTRY_SUBREGION_ID'; ENDPOINT_NUMBER ENDPOINT_VALUE --------------- -------------- 0 52792 2 52793 3 52795 4 52798 7 52799
図11-4に、高さ調整済ヒストグラムを図示します。この図では、値はコインとして表されています。
バケット番号とエンドポイント番号は同じです。オプティマイザはそれぞれのバケットの最後の行の値をエンドポイント値として記録し、最小値が最初のバケットのエンドポイント値であり、最大値が最後のバケットの最大値であることを確認します。この例では、オプティマイザは、最小値
52792
がバケットのエンドポイントとなるようにバケット0
を追加しています。オプティマイザは、指定された7個のヒストグラム・バケットに23行を均一に配分する必要があります。そのため、それぞれのバケットに入る行数はおよそ3行です。ただし、オプティマイザは同じエンドポイントでバケットを圧縮します。そのため、バケット
1
には値52793
のインスタンスが2つ、バケット2
には値52793
のインスタンスが3つ含まれます。さらに、オプティマイザは値52793
の5つのインスタンスすべてをバケット2
に入れます。同様に、オプティマイザは、バケット5
、6
および7
に、各バケットのエンドポイントとして52799
を設定してそれぞれ3つの値を入れるかわりに、値52799
の9個のインスタンスすべてをバケット7
に入れます。この例では、現在のエンドポイント番号と前のエンドポイント番号との差が1であるため、バケット
3
および4
には非ポピュラー値が含まれます。オプティマイザは、これらの値のカーディナリティを密度に基づいて計算します。残りのバケットにはポピュラー値が含まれます。オプティマイザは、これらの値のカーディナリティをエンドポイント番号に基づいて計算します。
関連項目:
-
DBMS_STATS.GATHER_TABLE_STATS
プロシージャについて学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。 -
USER_TAB_COL_STATISTICS
ビューについて学習するには、『Oracle Databaseリファレンス』を参照してください。 -
USER_HISTOGRAMS
ビューについて学習するには、『Oracle Databaseリファレンス』を参照してください。
11.8 ハイブリッド・ヒストグラム
ハイブリッド・ヒストグラムは、高さ調整済ヒストグラムと頻度ヒストグラムの両方の特性を組み合せたものです。「両者の長所を活かす」アプローチにより、オプティマイザは、一部の状況で、より適切な選択性の見積りを得ることができます。
高さ調整済ヒストグラムでは、ほぼポピュラーな値について正確ではない見積りが作成される場合があります。たとえば、1つのバケットのみのエンドポイント値として出現するが、2つのバケットをほぼ占めている値は、ポピュラー値とはみなされません。
この問題を解決するため、ハイブリッド・ヒストグラムでは、複数のバケットを占める値がないように値が配分され、エンドポイント繰返しカウント値が格納されます。これは、ヒストグラム内の各エンドポイント(バケット)について、エンドポイント値が繰り返された回数です。繰返しカウントを使用することで、オプティマイザは、ほぼポピュラーな値についての正確な見積りを得ることができます。
この項では、次の項目について説明します。
11.8.1 エンドポイント繰返しカウントの仕組み
バケットに配分されたコインの例えは、エンドポイント繰返しカウントの仕組みを示しています。
次の図は、低い値から高い値に分類したcoins
列を示しています。
DBMS_STATS.GATHER_TABLE_STATS
のmethod_opt
引数をFOR ALL COLUMNS SIZE 3
に設定して、この表の統計を収集します。この場合、オプティマイザはまず、次の図に示されているようにcoins
列の値を3つのバケットにグループ化します。
バケット境界により、値の一部のオカレンスがあるバケットに入り、別のオカレンスが別のバケットに入るように、値が分けられた場合、オプティマイザは、値のすべてのオカレンスが含まれるように、バケット境界(および他のすべての続くバケット境界)を移動します。たとえば、オプティマイザは、値5
を、すべてが最初のバケットに入るように移動し、値25
を、すべてが2番目のバケットに入るように移動します。
エンドポイント繰返しカウントは、対応するバケットのエンドポイント(右のバケット境界にある値)が繰り返される回数を測定します。たとえば、最初のバケットで、値5
が3回繰り返されているため、エンドポイント繰返しカウントは3
です。
高さ調整済ヒストグラムでは、ハイブリッド・ヒストグラムほどの情報量は格納されません。繰返しカウントを使用することで、オプティマイザは、エンドポイント値のオカレンスがいくつ存在するかを正確に特定できます。たとえば、オプティマイザは、値5
は3回、値25
は4回、値100
は2回出現していると認識できます。頻度情報は、オプティマイザがより適切なカーディナリティの見積りを生成するのに役立ちます。
11.8.2 ハイブリッド・ヒストグラムの基準
ハイブリッド・ヒストグラムと上位頻度ヒストグラムを区別するための唯一の基準は、上位n個の頻度の値が内部しきい値pより小さいことです。
「Oracle Databaseによるヒストグラム・タイプの選択方法」の論理図に示すように、次の基準を満たす場合に、データベースはハイブリッド・ヒストグラムを作成します。
-
NDVがnより大きい(nはヒストグラム・バケットの数(デフォルトは
254
)です)。 -
上位頻度ヒストグラムの基準が適用されない。
これは、上位nの頻出値によって占められている行の割合がしきい値pより小さいことを示す別の方法です。ここで、pは
(1-(1/
n
))*100
です。 -
DBMS_STATS
統計収集プロシージャのestimate_percent
パラメータがAUTO_SAMPLE_SIZE
に設定されている。ユーザーが独自の率を指定した場合、データベースでは、頻度ヒストグラムまたは高さ調整済ヒストグラムが作成されます。
関連項目:
-
estimate_percent
パラメータについてさらに学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください
11.8.3 ハイブリッド・ヒストグラムの生成
このシナリオでは、サンプル・スキーマを使用して、ハイブリッド・ヒストグラムを生成する方法を説明します。
前提条件
このシナリオでは、sh.products.prod_subcategory_id
列にハイブリッド・ヒストグラムを生成することを想定しています。この表には72行が含まれています。prod_subcategory_id
列には、22個の個別値があります。
ハイブリッド・ヒストグラムを生成するには:
-
10個のバケットを指定して、
sh.products
およびprod_subcategory_id
列の統計を収集します。たとえば、次のコマンドを入力します。
BEGIN DBMS_STATS.GATHER_TABLE_STATS ( ownname => 'SH' , tabname => 'PRODUCTS' , method_opt => 'FOR COLUMNS PROD_SUBCATEGORY_ID SIZE 10' ); END;
-
各個別値が占める行数を問い合せます。
たとえば、次の問合せを使用します(出力例も示します)。
SELECT COUNT(prod_subcategory_id) AS NUM_OF_ROWS, prod_subcategory_id FROM products GROUP BY prod_subcategory_id ORDER BY 1 DESC; NUM_OF_ROWS PROD_SUBCATEGORY_ID ----------- ------------------- 8 2014 7 2055 6 2032 6 2054 5 2056 5 2031 5 2042 5 2051 4 2036 3 2043 2 2033 2 2034 2 2013 2 2012 2 2053 2 2035 1 2022 1 2041 1 2044 1 2011 1 2021 1 2052 22 rows selected.
この列には22個の個別値があります。バケットの数(10)が22よりも小さいので、オプティマイザは頻度ヒストグラムを作成できません。オプティマイザはハイブリッド・ヒストグラムと上位頻度ヒストグラムの両方を検討します。上位頻度ヒストグラムに該当するには、上位10の頻出値によって占められている行の割合がしきい値p以上である必要があります。この場合、pは(1-(1/10))*100、つまり90%です。しかし、この場合、上位10の頻出値が占めているのは72行のうち54行、つまり全体の75%にしかなりません。したがって、上位頻度ヒストグラムの基準には該当しないため、オプティマイザはハイブリッド・ヒストグラムを選択します。
-
country_subregion_id
列のヒストグラム情報を問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT TABLE_NAME, COLUMN_NAME, NUM_DISTINCT, HISTOGRAM FROM USER_TAB_COL_STATISTICS WHERE TABLE_NAME='PRODUCTS' AND COLUMN_NAME='PROD_SUBCATEGORY_ID'; TABLE_NAME COLUMN_NAME NUM_DISTINCT HISTOGRAM ---------- ------------------- ------------ --------- PRODUCTS PROD_SUBCATEGORY_ID 22 HYBRID
-
country_subregion_id
列のエンドポイント番号、エンドポイント値およびエンドポイント繰返しカウントを問い合せます。たとえば、次の問合せを使用します(出力例も示します)。
SELECT ENDPOINT_NUMBER, ENDPOINT_VALUE, ENDPOINT_REPEAT_COUNT FROM USER_HISTOGRAMS WHERE TABLE_NAME='PRODUCTS' AND COLUMN_NAME='PROD_SUBCATEGORY_ID' ORDER BY 1; ENDPOINT_NUMBER ENDPOINT_VALUE ENDPOINT_REPEAT_COUNT --------------- -------------- --------------------- 1 2011 1 13 2014 8 26 2032 6 36 2036 4 45 2043 3 51 2051 5 52 2052 1 54 2053 2 60 2054 6 72 2056 5 10 rows selected.
高さ調整済ヒストグラムでは、オプティマイザは、指定された10個のヒストグラム・バケットに72行を均一に配分する必要があります。そのため、それぞれのバケットに入る行数はおよそ7行です。これはハイブリッド・ヒストグラムなので、オプティマイザは、1つの値が1個より多くのバケットを占めないように値を分配します。たとえば、オプティマイザは値
2036
の一部のインスタンスを別のバケットに入れることはしません。すべてのインスタンスをバケット36
に入れます。エンドポイント繰返しカウントは、バケット内で最も高い値が繰り返される回数を示します。これらの値のエンドポイント番号と繰返しカウントを使用することによって、オプティマイザはカーディナリティを見積ることができます。たとえば、バケット
36
には値2033
、2034
、2035
および2036
のインスタンスが格納されています。エンドポイント値2036
のエンドポイント繰返しカウントは4
です。そのため、オプティマイザはこの値に4つのインスタンスが存在することを認識しています。2033
など、エンドポイントではない値の場合、オプティマイザは密度を使用してカーディナリティを見積ります。
関連項目:
-
DBMS_STATS.GATHER_TABLE_STATS
プロシージャについて学習するには、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。 -
USER_TAB_COL_STATISTICS
ビューについて学習するには、Oracle Databaseリファレンスを参照してください -
USER_HISTOGRAMS
ビューについて学習するには、Oracle Databaseリファレンスを参照してください