]> granicus.if.org Git - postgresql/blobdiff - doc/src/sgml/gist.sgml
Trim trailing whitespace
[postgresql] / doc / src / sgml / gist.sgml
index 1b6fa1a8817bb032c44e4bee524c40fc80254123..b3cc347e5ccc732e44d4ec549b1922f72fd4cb4d 100644 (file)
 
 </sect1>
 
+<sect1 id="gist-builtin-opclasses">
+ <title>Built-in Operator Classes</title>
+
+ <para>
+  The core <productname>PostgreSQL</> distribution
+  includes the <acronym>GiST</acronym> operator classes shown in
+  <xref linkend="gist-builtin-opclasses-table">.
+  (Some of the optional modules described in <xref linkend="contrib">
+  provide additional <acronym>GiST</acronym> operator classes.)
+ </para>
+
+  <table id="gist-builtin-opclasses-table">
+   <title>Built-in <acronym>GiST</acronym> Operator Classes</title>
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Indexed Data Type</entry>
+      <entry>Indexable Operators</entry>
+      <entry>Ordering Operators</entry>
+     </row>
+    </thead>
+    <tbody>
+     <row>
+      <entry><literal>box_ops</></entry>
+      <entry><type>box</></entry>
+      <entry>
+       <literal>&amp;&amp;</>
+       <literal>&amp;&gt;</>
+       <literal>&amp;&lt;</>
+       <literal>&amp;&lt;|</>
+       <literal>&gt;&gt;</>
+       <literal>&lt;&lt;</>
+       <literal>&lt;&lt;|</>
+       <literal>&lt;@</>
+       <literal>@&gt;</>
+       <literal>@</>
+       <literal>|&amp;&gt;</>
+       <literal>|&gt;&gt;</>
+       <literal>~</>
+       <literal>~=</>
+      </entry>
+      <entry>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>circle_ops</></entry>
+      <entry><type>circle</></entry>
+      <entry>
+       <literal>&amp;&amp;</>
+       <literal>&amp;&gt;</>
+       <literal>&amp;&lt;</>
+       <literal>&amp;&lt;|</>
+       <literal>&gt;&gt;</>
+       <literal>&lt;&lt;</>
+       <literal>&lt;&lt;|</>
+       <literal>&lt;@</>
+       <literal>@&gt;</>
+       <literal>@</>
+       <literal>|&amp;&gt;</>
+       <literal>|&gt;&gt;</>
+       <literal>~</>
+       <literal>~=</>
+      </entry>
+      <entry>
+       <literal>&lt;-&gt;</>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>inet_ops</></entry>
+      <entry><type>inet</>, <type>cidr</></entry>
+      <entry>
+       <literal>&amp;&amp;</>
+       <literal>&gt;&gt;</>
+       <literal>&gt;&gt;=</>
+       <literal>&gt;</>
+       <literal>&gt;=</>
+       <literal>&lt;&gt;</>
+       <literal>&lt;&lt;</>
+       <literal>&lt;&lt;=</>
+       <literal>&lt;</>
+       <literal>&lt;=</>
+       <literal>=</>
+      </entry>
+      <entry>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>point_ops</></entry>
+      <entry><type>point</></entry>
+      <entry>
+       <literal>&gt;&gt;</>
+       <literal>&gt;^</>
+       <literal>&lt;&lt;</>
+       <literal>&lt;@</>
+       <literal>&lt;@</>
+       <literal>&lt;@</>
+       <literal>&lt;^</>
+       <literal>~=</>
+      </entry>
+      <entry>
+       <literal>&lt;-&gt;</>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>poly_ops</></entry>
+      <entry><type>polygon</></entry>
+      <entry>
+       <literal>&amp;&amp;</>
+       <literal>&amp;&gt;</>
+       <literal>&amp;&lt;</>
+       <literal>&amp;&lt;|</>
+       <literal>&gt;&gt;</>
+       <literal>&lt;&lt;</>
+       <literal>&lt;&lt;|</>
+       <literal>&lt;@</>
+       <literal>@&gt;</>
+       <literal>@</>
+       <literal>|&amp;&gt;</>
+       <literal>|&gt;&gt;</>
+       <literal>~</>
+       <literal>~=</>
+      </entry>
+      <entry>
+       <literal>&lt;-&gt;</>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>range_ops</></entry>
+      <entry>any range type</entry>
+      <entry>
+       <literal>&amp;&amp;</>
+       <literal>&amp;&gt;</>
+       <literal>&amp;&lt;</>
+       <literal>&gt;&gt;</>
+       <literal>&lt;&lt;</>
+       <literal>&lt;@</>
+       <literal>-|-</>
+       <literal>=</>
+       <literal>@&gt;</>
+       <literal>@&gt;</>
+      </entry>
+      <entry>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>tsquery_ops</></entry>
+      <entry><type>tsquery</></entry>
+      <entry>
+       <literal>&lt;@</>
+       <literal>@&gt;</>
+      </entry>
+      <entry>
+      </entry>
+     </row>
+     <row>
+      <entry><literal>tsvector_ops</></entry>
+      <entry><type>tsvector</></entry>
+      <entry>
+       <literal>@@</>
+      </entry>
+      <entry>
+      </entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+
+ <para>
+  For historical reasons, the <literal>inet_ops</> operator class is
+  not the default class for types <type>inet</> and <type>cidr</>.
+  To use it, mention the class name in <command>CREATE INDEX</>,
+  for example
+<programlisting>
+CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops);
+</programlisting>
+ </para>
+
+</sect1>
+
 <sect1 id="gist-extensibility">
  <title>Extensibility</title>
 
    reuse, and a clean interface.
   </para>
 
-</sect1>
-
-<sect1 id="gist-implementation">
- <title>Implementation</title>
-
  <para>
    There are seven methods that an index operator class for
-   <acronym>GiST</acronym> must provide, and an eighth that is optional.
+   <acronym>GiST</acronym> must provide, and two that are optional.
    Correctness of the index is ensured
    by proper implementation of the <function>same</>, <function>consistent</>
    and <function>union</> methods, while efficiency (size and speed) of the
    of the <command>CREATE OPERATOR CLASS</> command can be used.
    The optional eighth method is <function>distance</>, which is needed
    if the operator class wishes to support ordered scans (nearest-neighbor
-   searches).
+   searches). The optional ninth method <function>fetch</> is needed if the
+   operator class wishes to support index-only scans.
  </para>
 
  <variablelist>
@@ -151,7 +327,6 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_consistent(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_consistent);
 
 Datum
@@ -184,9 +359,20 @@ my_consistent(PG_FUNCTION_ARGS)
        the value being looked up in the index. The <literal>StrategyNumber</>
        parameter indicates which operator of your operator class is being
        applied &mdash; it matches one of the operator numbers in the
-       <command>CREATE OPERATOR CLASS</> command.  Depending on what operators
-       you have included in the class, the data type of <varname>query</> could
-       vary with the operator, but the above skeleton assumes it doesn't.
+       <command>CREATE OPERATOR CLASS</> command.
+      </para>
+
+      <para>
+       Depending on which operators you have included in the class, the data
+       type of <varname>query</> could vary with the operator, since it will
+       be whatever type is on the righthand side of the operator, which might
+       be different from the indexed data type appearing on the lefthand side.
+       (The above code skeleton assumes that only one type is possible; if
+       not, fetching the <varname>query</> argument value would have to depend
+       on the operator.)  It is recommended that the SQL declaration of
+       the <function>consistent</> function use the opclass's indexed data
+       type for the <varname>query</> argument, even though the actual type
+       might be something else depending on the operator.
       </para>
 
      </listitem>
@@ -206,7 +392,7 @@ my_consistent(PG_FUNCTION_ARGS)
 
 <programlisting>
 CREATE OR REPLACE FUNCTION my_union(internal, internal)
-RETURNS internal
+RETURNS storage_type
 AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT;
 </programlisting>
@@ -214,7 +400,6 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_union(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_union);
 
 Datum
@@ -260,9 +445,21 @@ my_union(PG_FUNCTION_ARGS)
       </para>
 
       <para>
-        The <function>union</> implementation function should return a
-        pointer to newly <function>palloc()</>ed memory. You can't just
-        return whatever the input is.
+        The result of the <function>union</> function must be a value of the
+        index's storage type, whatever that is (it might or might not be
+        different from the indexed column's type).  The <function>union</>
+        function should return a pointer to newly <function>palloc()</>ed
+        memory. You can't just return the input value as-is, even if there is
+        no type change.
+      </para>
+
+      <para>
+       As shown above, the <function>union</> function's
+       first <type>internal</> argument is actually
+       a <structname>GistEntryVector</> pointer.  The second argument is a
+       pointer to an integer variable, which can be ignored.  (It used to be
+       required that the <function>union</> function store the size of its
+       result value into that variable, but this is no longer necessary.)
       </para>
      </listitem>
     </varlistentry>
@@ -288,7 +485,6 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_compress(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_compress);
 
 Datum
@@ -324,12 +520,6 @@ my_compress(PG_FUNCTION_ARGS)
        type you're converting to in order to compress your leaf nodes, of
        course.
       </para>
-
-      <para>
-        Depending on your needs, you could also need to care about
-        compressing <literal>NULL</> values in there, storing for example
-        <literal>(Datum) 0</> like <literal>gist_circle_compress</> does.
-      </para>
      </listitem>
     </varlistentry>
 
@@ -339,7 +529,7 @@ my_compress(PG_FUNCTION_ARGS)
       <para>
        The reverse of the <function>compress</function> method.  Converts the
        index representation of the data item into a format that can be
-       manipulated by the database.
+       manipulated by the other GiST methods in the operator class.
       </para>
 
       <para>
@@ -355,7 +545,6 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_decompress(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_decompress);
 
 Datum
@@ -395,7 +584,6 @@ LANGUAGE C STRICT;  -- in some cases penalty functions need not be strict
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_penalty(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_penalty);
 
 Datum
@@ -411,6 +599,12 @@ my_penalty(PG_FUNCTION_ARGS)
     PG_RETURN_POINTER(penalty);
 }
 </programlisting>
+
+        For historical reasons, the <function>penalty</> function doesn't
+        just return a <type>float</> result; instead it has to store the value
+        at the location indicated by the third argument.  The return
+        value per se is ignored, though it's conventional to pass back the
+        address of that argument.
       </para>
 
       <para>
@@ -444,16 +638,15 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_picksplit(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_picksplit);
 
 Datum
 my_picksplit(PG_FUNCTION_ARGS)
 {
     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     OffsetNumber maxoff = entryvec-&gt;n - 1;
     GISTENTRY  *ent = entryvec-&gt;vector;
-    GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
     int         i,
                 nbytes;
     OffsetNumber *left,
@@ -519,6 +712,11 @@ my_picksplit(PG_FUNCTION_ARGS)
     PG_RETURN_POINTER(v);
 }
 </programlisting>
+
+       Notice that the <function>picksplit</> function's result is delivered
+       by modifying the passed-in <structname>v</> structure.  The return
+       value per se is ignored, though it's conventional to pass back the
+       address of <structname>v</>.
       </para>
 
       <para>
@@ -536,13 +734,15 @@ my_picksplit(PG_FUNCTION_ARGS)
      <listitem>
       <para>
        Returns true if two index entries are identical, false otherwise.
+       (An <quote>index entry</> is a value of the index's storage type,
+       not necessarily the original indexed column's type.)
       </para>
 
       <para>
         The <acronym>SQL</> declaration of the function must look like this:
 
 <programlisting>
-CREATE OR REPLACE FUNCTION my_same(internal, internal, internal)
+CREATE OR REPLACE FUNCTION my_same(storage_type, storage_type, internal)
 RETURNS internal
 AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT;
@@ -551,7 +751,6 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_same(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_same);
 
 Datum
@@ -568,7 +767,9 @@ my_same(PG_FUNCTION_ARGS)
 
         For historical reasons, the <function>same</> function doesn't
         just return a Boolean result; instead it has to store the flag
-        at the location indicated by the third argument.
+        at the location indicated by the third argument.  The return
+        value per se is ignored, though it's conventional to pass back the
+        address of that argument.
       </para>
      </listitem>
     </varlistentry>
@@ -593,7 +794,7 @@ my_same(PG_FUNCTION_ARGS)
         The <acronym>SQL</> declaration of the function must look like this:
 
 <programlisting>
-CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid)
+CREATE OR REPLACE FUNCTION my_distance(internal, data_type, smallint, oid, internal)
 RETURNS float8
 AS 'MODULE_PATHNAME'
 LANGUAGE C STRICT;
@@ -602,7 +803,6 @@ LANGUAGE C STRICT;
         And the matching code in the C module could then follow this skeleton:
 
 <programlisting>
-Datum       my_distance(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(my_distance);
 
 Datum
@@ -612,6 +812,7 @@ my_distance(PG_FUNCTION_ARGS)
     data_type  *query = PG_GETARG_DATA_TYPE_P(1);
     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
     /* Oid subtype = PG_GETARG_OID(3); */
+    /* bool *recheck = (bool *) PG_GETARG_POINTER(4); */
     data_type  *key = DatumGetDataType(entry-&gt;key);
     double      retval;
 
@@ -624,53 +825,155 @@ my_distance(PG_FUNCTION_ARGS)
 </programlisting>
 
        The arguments to the <function>distance</> function are identical to
-       the arguments of the <function>consistent</> function, except that no
-       recheck flag is used.  The distance to a leaf index entry must always
-       be determined exactly, since there is no way to re-order the tuples
-       once they are returned.  Some approximation is allowed when determining
-       the distance to an internal tree node, so long as the result is never
-       greater than any child's actual distance.  Thus, for example, distance
-       to a bounding box is usually sufficient in geometric applications.  The
-       result value can be any finite <type>float8</> value.  (Infinity and
-       minus infinity are used internally to handle cases such as nulls, so it
-       is not recommended that <function>distance</> functions return these
-       values.)
+       the arguments of the <function>consistent</> function.
+      </para>
+
+      <para>
+       Some approximation is allowed when determining the distance, so long
+       as the result is never greater than the entry's actual distance. Thus,
+       for example, distance to a bounding box is usually sufficient in
+       geometric applications.  For an internal tree node, the distance
+       returned must not be greater than the distance to any of the child
+       nodes. If the returned distance is not exact, the function must set
+       <literal>*recheck</> to true. (This is not necessary for internal tree
+       nodes; for them, the calculation is always assumed to be inexact.) In
+       this case the executor will calculate the accurate distance after
+       fetching the tuple from the heap, and reorder the tuples if necessary.
+      </para>
+
+      <para>
+       If the distance function returns <literal>*recheck = true</> for any
+       leaf node, the original ordering operator's return type must
+       be <type>float8</> or <type>float4</>, and the distance function's
+       result values must be comparable to those of the original ordering
+       operator, since the executor will sort using both distance function
+       results and recalculated ordering-operator results.  Otherwise, the
+       distance function's result values can be any finite <type>float8</>
+       values, so long as the relative order of the result values matches the
+       order returned by the ordering operator.  (Infinity and minus infinity
+       are used internally to handle cases such as nulls, so it is not
+       recommended that <function>distance</> functions return these values.)
       </para>
 
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><function>fetch</></term>
+     <listitem>
+      <para>
+       Converts the compressed index representation of a data item into the
+       original data type, for index-only scans. The returned data must be an
+       exact, non-lossy copy of the originally indexed value.
+      </para>
+
+      <para>
+        The <acronym>SQL</> declaration of the function must look like this:
+
+<programlisting>
+CREATE OR REPLACE FUNCTION my_fetch(internal)
+RETURNS internal
+AS 'MODULE_PATHNAME'
+LANGUAGE C STRICT;
+</programlisting>
+
+        The argument is a pointer to a <structname>GISTENTRY</> struct. On
+        entry, its <structfield>key</> field contains a non-NULL leaf datum in
+        compressed form. The return value is another <structname>GISTENTRY</>
+        struct, whose <structfield>key</> field contains the same datum in its
+        original, uncompressed form. If the opclass's compress function does
+        nothing for leaf entries, the <function>fetch</> method can return the
+        argument as-is.
+       </para>
+
+       <para>
+        The matching code in the C module could then follow this skeleton:
+
+<programlisting>
+PG_FUNCTION_INFO_V1(my_fetch);
+
+Datum
+my_fetch(PG_FUNCTION_ARGS)
+{
+    GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+    input_data_type *in = DatumGetP(entry->key);
+    fetched_data_type *fetched_data;
+    GISTENTRY  *retval;
+
+    retval = palloc(sizeof(GISTENTRY));
+    fetched_data = palloc(sizeof(fetched_data_type));
+
+    /*
+     * Convert 'fetched_data' into the a Datum of the original datatype.
+     */
+
+    /* fill *retval from fetch_data. */
+    gistentryinit(*retval, PointerGetDatum(converted_datum),
+                  entry->rel, entry->page, entry->offset, FALSE);
+
+    PG_RETURN_POINTER(retval);
+}
+</programlisting>
+      </para>
+
+      <para>
+       If the compress method is lossy for leaf entries, the operator class
+       cannot support index-only scans, and must not define
+       a <function>fetch</> function.
+      </para>
+
+     </listitem>
+    </varlistentry>
   </variablelist>
 
+  <para>
+   All the GiST support methods are normally called in short-lived memory
+   contexts; that is, <varname>CurrentMemoryContext</> will get reset after
+   each tuple is processed.  It is therefore not very important to worry about
+   pfree'ing everything you palloc.  However, in some cases it's useful for a
+   support method to cache data across repeated calls.  To do that, allocate
+   the longer-lived data in <literal>fcinfo-&gt;flinfo-&gt;fn_mcxt</>, and
+   keep a pointer to it in <literal>fcinfo-&gt;flinfo-&gt;fn_extra</>.  Such
+   data will survive for the life of the index operation (e.g., a single GiST
+   index scan, index build, or index tuple insertion).  Be careful to pfree
+   the previous value when replacing a <literal>fn_extra</> value, or the leak
+   will accumulate for the duration of the operation.
+  </para>
+
+</sect1>
+
+<sect1 id="gist-implementation">
+ <title>Implementation</title>
+
  <sect2 id="gist-buffering-build">
   <title>GiST buffering build</title>
   <para>
    Building large GiST indexes by simply inserting all the tuples tends to be
    slow, because if the index tuples are scattered across the index and the
    index is large enough to not fit in cache, the insertions need to perform
-   a lot of random I/O. PostgreSQL from version 9.2 supports a more efficient
-   method to build GiST indexes based on buffering, which can dramatically
-   reduce number of random I/O needed for non-ordered data sets. For
-   well-ordered datasets the benefit is smaller or non-existent, because
-   only a small number of pages receive new tuples at a time, and those pages
-   fit in cache even if the index as whole does not.
+   a lot of random I/O.  Beginning in version 9.2, PostgreSQL supports a more
+   efficient method to build GiST indexes based on buffering, which can
+   dramatically reduce the number of random I/Os needed for non-ordered data
+   sets. For well-ordered data sets the benefit is smaller or non-existent,
+   because only a small number of pages receive new tuples at a time, and
+   those pages fit in cache even if the index as whole does not.
   </para>
 
   <para>
    However, buffering index build needs to call the <function>penalty</>
    function more often, which consumes some extra CPU resources. Also, the
    buffers used in the buffering build need temporary disk space, up to
-   the size of the resulting index. Buffering can also infuence the quality
-   of the produced index, in both positive and negative directions. That
+   the size of the resulting index. Buffering can also influence the quality
+   of the resulting index, in both positive and negative directions. That
    influence depends on various factors, like the distribution of the input
-   data and operator class implementation.
+   data and the operator class implementation.
   </para>
 
   <para>
-   By default, the index build switches to the buffering method when the
+   By default, a GiST index build switches to the buffering method when the
    index size reaches <xref linkend="guc-effective-cache-size">. It can
-   be manually turned on or off by the <literal>BUFFERING</literal> parameter
-   to the CREATE INDEX clause. The default behavior is good for most cases,
+   be manually turned on or off by the <literal>buffering</literal> parameter
+   to the CREATE INDEX command. The default behavior is good for most cases,
    but turning buffering off might speed up the build somewhat if the input
    data is ordered.
   </para>