1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Add support for index-only scans in GiST.

This adds a new GiST opclass method, 'fetch', which is used to reconstruct
the original Datum from the value stored in the index. Also, the 'canreturn'
index AM interface function gains a new 'attno' argument. That makes it
possible to use index-only scans on a multi-column index where some of the
opclasses support index-only scans but some do not.

This patch adds support in the box and point opclasses. Other opclasses
can added later as follow-on patches (btree_gist would be particularly
interesting).

Anastasia Lubennikova, with additional fixes and modifications by me.
This commit is contained in:
Heikki Linnakangas
2015-03-26 19:12:00 +02:00
parent 8fa393a6d7
commit d04c8ed904
24 changed files with 575 additions and 73 deletions

View File

@ -724,8 +724,8 @@
<entry><structfield>amcanreturn</structfield></entry>
<entry><type>regproc</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>Function to check whether index supports index-only scans,
or zero if none</entry>
<entry>Function to check whether an index column supports index-only
scans. Can be zero if index-only scans are never supported.</entry>
</row>
<row>

View File

@ -266,7 +266,7 @@ CREATE INDEX ON my_table USING gist (my_inet_column inet_ops);
<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
@ -282,7 +282,8 @@ CREATE INDEX ON my_table USING gist (my_inet_column inet_ops);
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>
@ -506,7 +507,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>
@ -807,6 +808,72 @@ my_distance(PG_FUNCTION_ARGS)
</listitem>
</varlistentry>
<varlistentry>
<term><function>fetch</></term>
<listitem>
<para>
Converts the compressed index representation of the 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 'key' field contains a non-NULL leaf datum in its
compressed form. The return value is another <structname>GISTENTRY</>
struct, whose 'key' field contains the same datum in the original,
uncompressed form. If the opclass' compress function does nothing for
leaf entries, the fetch method can return the argument as is.
</para>
<para>
The matching code in the C module could then follow this skeleton:
<programlisting>
Datum my_fetch(PG_FUNCTION_ARGS);
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 'fetch'
function.
</para>
</listitem>
</varlistentry>
</variablelist>
<para>

View File

@ -274,14 +274,15 @@ amvacuumcleanup (IndexVacuumInfo *info,
<para>
<programlisting>
bool
amcanreturn (Relation indexRelation);
amcanreturn (Relation indexRelation, int attno);
</programlisting>
Check whether the index can support <firstterm>index-only scans</> by
returning the indexed column values for an index entry in the form of an
<structname>IndexTuple</structname>. Return TRUE if so, else FALSE. If the index AM can never
support index-only scans (an example is hash, which stores only
the hash values not the original data), it is sufficient to set its
<structfield>amcanreturn</> field to zero in <structname>pg_am</>.
Check whether the index can support <firstterm>index-only scans</> on the
given column, by returning the indexed column values for an index entry in
the form of an <structname>IndexTuple</structname>. The attribute number
is 1-based, i.e. the first columns attno is 1. Returns TRUE if supported,
else FALSE. If the access method does not support index-only scans at all,
the <structfield>amcanreturn</> field in its <structname>pg_am</> row can
be set to zero.
</para>
<para>