From d04c8ed9044eccebce043143a930617e3998c005 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Thu, 26 Mar 2015 19:12:00 +0200 Subject: 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. --- doc/src/sgml/catalogs.sgml | 4 +-- doc/src/sgml/gist.sgml | 73 ++++++++++++++++++++++++++++++++++++++++++++-- doc/src/sgml/indexam.sgml | 15 +++++----- 3 files changed, 80 insertions(+), 12 deletions(-) (limited to 'doc/src') diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index dfed546f513..d0b78f27827 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -724,8 +724,8 @@ amcanreturn regproc pg_proc.oid - Function to check whether index supports index-only scans, - or zero if none + Function to check whether an index column supports index-only + scans. Can be zero if index-only scans are never supported. diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml index 31ce2790047..e7d1ff9d83f 100644 --- a/doc/src/sgml/gist.sgml +++ b/doc/src/sgml/gist.sgml @@ -266,7 +266,7 @@ CREATE INDEX ON my_table USING gist (my_inet_column inet_ops); There are seven methods that an index operator class for - GiST must provide, and an eighth that is optional. + GiST must provide, and two that are optional. Correctness of the index is ensured by proper implementation of the same, consistent and 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 CREATE OPERATOR CLASS command can be used. The optional eighth method is distance, which is needed if the operator class wishes to support ordered scans (nearest-neighbor - searches). + searches). The optional ninth method fetch is needed if the + operator class wishes to support index-only scans. @@ -506,7 +507,7 @@ my_compress(PG_FUNCTION_ARGS) The reverse of the compress 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. @@ -807,6 +808,72 @@ my_distance(PG_FUNCTION_ARGS) + + fetch + + + 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. + + + + The SQL declaration of the function must look like this: + + +CREATE OR REPLACE FUNCTION my_fetch(internal) +RETURNS internal +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; + + + The argument is a pointer to a GISTENTRY struct. On + entry, its 'key' field contains a non-NULL leaf datum in its + compressed form. The return value is another 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. + + + + The matching code in the C module could then follow this skeleton: + + +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); +} + + + + + If the compress method is lossy for leaf entries, the operator class + cannot support index-only scans, and must not define a 'fetch' + function. + + + + diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 157047a23ab..1c09bae3955 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -274,14 +274,15 @@ amvacuumcleanup (IndexVacuumInfo *info, bool -amcanreturn (Relation indexRelation); +amcanreturn (Relation indexRelation, int attno); - Check whether the index can support index-only scans by - returning the indexed column values for an index entry in the form of an - IndexTuple. 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 - amcanreturn field to zero in pg_am. + Check whether the index can support index-only scans on the + given column, by returning the indexed column values for an index entry in + the form of an IndexTuple. 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 amcanreturn field in its pg_am row can + be set to zero. -- cgit v1.2.3