バージョンごとのドキュメント一覧

64.6. インデックスコスト推定関数 #

<title>Index Cost Estimation Functions</title>

The <function>amcostestimate</function> function is given information describing a possible index scan, including lists of WHERE and ORDER BY clauses that have been determined to be usable with the index. It must return estimates of the cost of accessing the index and the selectivity of the WHERE clauses (that is, the fraction of parent-table rows that will be retrieved during the index scan). For simple cases, nearly all the work of the cost estimator can be done by calling standard routines in the optimizer; the point of having an <function>amcostestimate</function> function is to allow index access methods to provide index-type-specific knowledge, in case it is possible to improve on the standard estimates. amcostestimate関数には、インデックスと共に使用できることが決まっているWHERE句およびORDER BY句のリストを含む、インデックススキャンの可能性を記述する情報が与えられます。 この関数はインデックスにアクセスするコストの概算とWHERE句の選択度(つまりインデックススキャンにて抽出される行の親テーブルにおける割合)を返さなくてはなりません。 単純な場合だと、ほとんどすべてのコスト概算の作業は、オプティマイザの標準ルーチンを呼び出すことで行われます。 amcostestimate関数を持つことの意味は、標準の概算を改善することができる場合に、インデックスアクセスメソッドがインデックス型固有の知識体系を提供することができるということです。

Each <function>amcostestimate</function> function must have the signature: それぞれのamcostestimate関数は以下のシグネチャを持たなければいけません。

void
amcostestimate (PlannerInfo *root,
                IndexPath *path,
                double loop_count,
                Cost *indexStartupCost,
                Cost *indexTotalCost,
                Selectivity *indexSelectivity,
                double *indexCorrelation,
                double *indexPages);

The first three parameters are inputs: 最初の3つのパラメータは入力です。

root

The planner's information about the query being processed. 処理されている問い合わせに関するプランナの情報。

path

The index access path being considered. All fields except cost and selectivity values are valid. 考慮されるインデックスアクセスパス。 コストと選択性値を除くすべてのフィールドが有効です。

loop_count

The number of repetitions of the index scan that should be factored into the cost estimates. This will typically be greater than one when considering a parameterized scan for use in the inside of a nestloop join. Note that the cost estimates should still be for just one scan; a larger <parameter>loop_count</parameter> means that it may be appropriate to allow for some caching effects across multiple scans. コスト概算の算出対象となるインデックススキャンが繰り返された回数です。 これは通常、ネステッドループ結合の内部で利用されるパラメータ化されたスキャンの回数よりも大きい値になります。 コスト概算は1回のスキャンのための値であることに注意してください。loop_countがより大きい場合、複数のスキャンにより得られる効果をみるには十分な値といえるでしょう。

The last five parameters are pass-by-reference outputs: 最後の5つのパラメータは参照渡しの出力です。

*indexStartupCost

Set to cost of index start-up processing インデックスの起動処理にかかるコストに設定されます。

*indexTotalCost

Set to total cost of index processing インデックス処理の全体のコストに設定されます。

*indexSelectivity

Set to index selectivity インデックスの選択度に設定されます。

*indexCorrelation

Set to correlation coefficient between index scan order and underlying table's order インデックススキャンの順番と背後のテーブルの順番間の相関係数に設定されます。

*indexPages

Set to number of index leaf pages インデックスのリーフページ数が設定されます。

Note that cost estimate functions must be written in C, not in SQL or any available procedural language, because they must access internal data structures of the planner/optimizer. コスト概算関数は、SQLやその他の手続き言語ではなく、C言語で書かれなければいけないことに注意してください。 理由はプランナ/オプティマイザの内部データ構造にアクセスしなければいけないためです。

The index access costs should be computed using the parameters used by <filename>src/backend/optimizer/path/costsize.c</filename>: a sequential disk block fetch has cost <varname>seq_page_cost</varname>, a nonsequential fetch has cost <varname>random_page_cost</varname>, and the cost of processing one index row should usually be taken as <varname>cpu_index_tuple_cost</varname>. In addition, an appropriate multiple of <varname>cpu_operator_cost</varname> should be charged for any comparison operators invoked during index processing (especially evaluation of the indexquals themselves). インデックスアクセスコストはsrc/backend/optimizer/path/costsize.cで使われる、逐次的なディスクブロックの取り出しにはseq_page_costのコストが、順不同の取り出しにはrandom_page_costのコストが、そして、1つのインデックス行の処理には通常cpu_index_tuple_costというコストがかかる、というパラメータで計算されなければなりません。 さらに、インデックス処理(特にindexquals自体の評価)の間に呼び出される比較演算すべてに対して、cpu_operator_costに適当な係数をかけたコストがかかります。

The access costs should include all disk and CPU costs associated with scanning the index itself, but <emphasis>not</emphasis> the costs of retrieving or processing the parent-table rows that are identified by the index. アクセスコストは、インデックス自身のスキャンと関係するすべてのディスクとCPUコストも含むべきですが、インデックスで識別される親テーブルの行の処理や抽出にかかるコストは含めてはいけません

The <quote>start-up cost</quote> is the part of the total scan cost that must be expended before we can begin to fetch the first row. For most indexes this can be taken as zero, but an index type with a high start-up cost might want to set it nonzero. 起動用コストは、最初の行を取り出し始めることができるようになる前に費やされなければならない総スキャンコストの一部です。 ほとんどのインデックスでは、これはゼロとすることができます。 しかし、高い起動用コストを持つインデックス種類ではこれを非ゼロにすることを勧めます。

The <parameter>indexSelectivity</parameter> should be set to the estimated fraction of the parent table rows that will be retrieved during the index scan. In the case of a lossy query, this will typically be higher than the fraction of rows that actually pass the given qual conditions. indexSelectivityは、インデックススキャンの間に抽出される親テーブルの行の概算された割合として設定されるべきです。 非可逆問い合わせの場合はこの値が、与えられた制約条件を実際に通過する行の割合よりも高くなることがよくあります。

The <parameter>indexCorrelation</parameter> should be set to the correlation (ranging between -1.0 and 1.0) between the index order and the table order. This is used to adjust the estimate for the cost of fetching rows from the parent table. indexCorrelationは、インデックスの順番とテーブルの順番の間の(-1.0から1.0までの間の値を取る)相関として設定されるべきです。 この値は、メインテーブルから行を取り出すためのコスト概算を調整するために使用されます。

The <parameter>indexPages</parameter> should be set to the number of leaf pages. This is used to estimate the number of workers for parallel index scan. indexPagesは、リーフページ数が設定されるべきです。 これは、パラレルインデックススキャンのワーカー数の見積もりに使用されます。

When <parameter>loop_count</parameter> is greater than one, the returned numbers should be averages expected for any one scan of the index. loop_countの値が1より大きい場合、戻り値はインデックスを利用した1回のスキャンを想定した平均値であるべきです。

コスト概算

<title>Cost Estimation</title>

A typical cost estimator will proceed as follows: 典型的なコスト概算は次のように進められます。

  1. Estimate and return the fraction of parent-table rows that will be visited based on the given qual conditions. In the absence of any index-type-specific knowledge, use the standard optimizer function <function>clauselist_selectivity()</function>: 与えられた制約条件に基づいて訪れられるメインテーブルの行の割合を概算して返します。 インデックス型固有の知識体系を持たない場合、標準のオプティマイザの関数であるclauselist_selectivity()を使用してください。

    *indexSelectivity = clauselist_selectivity(root, path->indexquals,
                                               path->indexinfo->rel->relid,
                                               JOIN_INNER, NULL);
    

  2. Estimate the number of index rows that will be visited during the scan. For many index types this is the same as <parameter>indexSelectivity</parameter> times the number of rows in the index, but it might be more. (Note that the index's size in pages and rows is available from the <literal>path-&gt;indexinfo</literal> struct.) スキャン中に訪れられるインデックスの行数を概算します。 多くのインデックス種類では、これはindexSelectivityとインデックスの中にある行数を掛けたものと等しいですが、それより多い場合もあります。 (ページおよび行内のインデックスのサイズはpath->indexinfo構造体から得ることができることに注意してください。)

  3. Estimate the number of index pages that will be retrieved during the scan. This might be just <parameter>indexSelectivity</parameter> times the index's size in pages. スキャン中に抽出されるインデックスページ数を概算します。 これは単にindexSelectivityにページ内のインデックスのサイズを掛けたものになるでしょう。

  4. Compute the index access cost. A generic estimator might do this: インデックスアクセスコストを計算します。 汎用的な概算においては以下のように行うでしょう。

    /*
    
     * Our generic assumption is that the index pages will be read
     * sequentially, so they cost seq_page_cost each, not random_page_cost.
     * Also, we charge for evaluation of the indexquals at each index row.
     * All the costs are assumed to be paid incrementally during the scan.
    
     * 一般的な仮定は、インデックスページは逐次的に読まれるので、
     * random_page_costではなく、それぞれseq_page_costが掛かるというものです。
     * 各インデックス行でのindexqualsの評価にもコストが掛かります。
     * コストはすべてスキャンの間に徐々に支払われると仮定します。
     */
    cost_qual_eval(&index_qual_cost, path->indexquals, root);
    *indexStartupCost = index_qual_cost.startup;
    *indexTotalCost = seq_page_cost * numIndexPages +
        (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples;
    

    However, the above does not account for amortization of index reads across repeated index scans. しかし、上では繰り返されるインデックススキャンにかかるインデックス読み込みについて減価償却を考慮していません。

  5. Estimate the index correlation. For a simple ordered index on a single field, this can be retrieved from pg_statistic. If the correlation is not known, the conservative estimate is zero (no correlation). インデックスの相関を概算します。 1つのフィールドに対する単純な順番のインデックスでは、これはpg_statisticから入手することができます。 相関が未知の場合、概算を用心深く考えるとゼロ(無相関)となります。

Examples of cost estimator functions can be found in <filename>src/backend/utils/adt/selfuncs.c</filename>. コスト概算関数の例はsrc/backend/utils/adt/selfuncs.cにあります。