<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/Attic/indexcost.sgml,v 2.2 2000/03/31 03:27:40 thomas Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/Attic/indexcost.sgml,v 2.3 2000/03/31 17:18:26 tgl Exp $
-->
<chapter>
</para>
</note>
-<!--
-I have written the attached bit of doco about the new index cost
-estimator procedure definition, but I am not sure where to put it.
-There isn't (AFAICT) any existing documentation about how to make
-a new kind of index, which would be the proper place for it.
-May I impose on you to find/make a place for this and mark it up
-properly?
-
-Also, doc/src/graphics/catalogs.ag needs to be updated, but I have
-no idea how. (The amopselect and amopnpages fields of pg_amop
-are gone; pg_am has a new field amcostestimate.)
-
- regards, tom lane
--->
+ <note>
+ <para>
+ This must eventually become part of a much larger chapter about
+ writing new index access methods.
+ </para>
+ </note>
<para>
Every index access method must provide a cost estimation function for
RelOptInfo *rel,
IndexOptInfo *index,
List *indexQuals,
- Cost *indexAccessCost,
+ Cost *indexStartupCost,
+ Cost *indexTotalCost,
Selectivity *indexSelectivity);
</programlisting>
</para>
<para>
- The last two parameters are pass-by-reference outputs:
+ The last three parameters are pass-by-reference outputs:
<variablelist>
<varlistentry>
- <term>*indexAccessCost</term>
+ <term>*indexStartupCost</term>
<listitem>
<para>
- Set to cost of index processing.
+ Set to cost of index startup processing
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>*indexTotalCost</term>
+ <listitem>
+ <para>
+ Set to total cost of index processing
</para>
</listitem>
</varlistentry>
</para>
<para>
- The indexAccessCost should be computed in the units used by
- src/backend/optimizer/path/costsize.c: a disk block fetch has cost 1.0,
- and the cost of processing one index tuple should usually be taken as
- cpu_index_page_weight (which is a user-adjustable optimizer parameter).
- The access cost should include all disk and CPU costs associated with
- scanning the index itself, but NOT the cost of retrieving or processing
+ The index access costs should be computed in the units used by
+ src/backend/optimizer/path/costsize.c: a sequential disk block fetch
+ has cost 1.0, a nonsequential fetch has cost random_page_cost, and
+ the cost of processing one index tuple should usually be taken as
+ cpu_index_tuple_cost (which is a user-adjustable optimizer parameter).
+ In addition, an appropriate multiple of cpu_operator_cost should be charged
+ for any comparison operators invoked during index processing (especially
+ evaluation of the indexQuals themselves).
+ </para>
+
+ <para>
+ The access costs should include all disk and CPU costs associated with
+ scanning the index itself, but NOT the costs of retrieving or processing
the main-table tuples that are identified by the index.
</para>
+ <para>
+ The "startup cost" is the part of the total scan cost that must be expended
+ before we can begin to fetch the first tuple. For most indexes this can
+ be taken as zero, but an index type with a high startup cost might want
+ to set it nonzero.
+ </para>
+
<para>
The indexSelectivity should be set to the estimated fraction of the main
table tuples that will be retrieved during the index scan. In the case
<para>
Estimate and return the fraction of main-table tuples that will be visited
based on the given qual conditions. In the absence of any index-type-specific
- knowledge, use the standard optimizer function clauselist_selec():
+ knowledge, use the standard optimizer function clauselist_selectivity():
<programlisting>
-*indexSelectivity = clauselist_selec(root, indexQuals);
+*indexSelectivity = clauselist_selectivity(root, indexQuals,
+ lfirsti(rel->relids));
</programlisting>
</para>
</step>
<step>
<para>
- Compute the index access cost as
+ Compute the index access cost. A generic estimator might do this:
<programlisting>
-*indexAccessCost = numIndexPages + cpu_index_page_weight * numIndexTuples;
+ /*
+ * Our generic assumption is that the index pages will be read
+ * sequentially, so they have cost 1.0 each, not random_page_cost.
+ * Also, we charge for evaluation of the indexquals at each index tuple.
+ * All the costs are assumed to be paid incrementally during the scan.
+ */
+ *indexStartupCost = 0;
+ *indexTotalCost = numIndexPages +
+ (cpu_index_tuple_cost + cost_qual_eval(indexQuals)) * numIndexTuples;
</programlisting>
</para>
</step>
<programlisting>
prorettype = 0
-pronargs = 6
-proargtypes = 0 0 0 0 0 0
+pronargs = 7
+proargtypes = 0 0 0 0 0 0 0
</programlisting>
We use zero ("opaque") for all the arguments since none of them have types