From f2e403803fe6deb8cff59ea09dff42c6163b2110 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Sun, 10 Mar 2019 11:36:47 +0300 Subject: Support for INCLUDE attributes in GiST indexes Similarly to B-tree, GiST index access method gets support of INCLUDE attributes. These attributes aren't used for tree navigation and aren't present in non-leaf pages. But they are present in leaf pages and can be fetched during index-only scan. The point of having INCLUDE attributes in GiST indexes is slightly different from the point of having them in B-tree. The main point of INCLUDE attributes in B-tree is to define UNIQUE constraint over part of attributes enabled for index-only scan. In GiST the main point of INCLUDE attributes is to use index-only scan for attributes, whose data types don't have GiST opclasses. Discussion: https://postgr.es/m/73A1A452-AD5F-40D4-BD61-978622FF75C1%40yandex-team.ru Author: Andrey Borodin, with small changes by me Reviewed-by: Andreas Karlsson --- src/backend/access/gist/gist.c | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) (limited to 'src/backend/access/gist/gist.c') diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c index 5ea774661a9..2ce5425ef98 100644 --- a/src/backend/access/gist/gist.c +++ b/src/backend/access/gist/gist.c @@ -75,7 +75,7 @@ gisthandler(PG_FUNCTION_ARGS) amroutine->amclusterable = true; amroutine->ampredlocks = true; amroutine->amcanparallel = false; - amroutine->amcaninclude = false; + amroutine->amcaninclude = true; amroutine->amkeytype = InvalidOid; amroutine->ambuild = gistbuild; @@ -1382,8 +1382,10 @@ gistSplit(Relation r, IndexTupleSize(itup[0]), GiSTPageSize, RelationGetRelationName(r)))); - memset(v.spl_lisnull, true, sizeof(bool) * giststate->tupdesc->natts); - memset(v.spl_risnull, true, sizeof(bool) * giststate->tupdesc->natts); + memset(v.spl_lisnull, true, + sizeof(bool) * giststate->nonLeafTupdesc->natts); + memset(v.spl_risnull, true, + sizeof(bool) * giststate->nonLeafTupdesc->natts); gistSplitByKey(r, page, itup, len, giststate, &v, 0); /* form left and right vector */ @@ -1461,9 +1463,23 @@ initGISTstate(Relation index) giststate->scanCxt = scanCxt; giststate->tempCxt = scanCxt; /* caller must change this if needed */ - giststate->tupdesc = index->rd_att; + giststate->leafTupdesc = index->rd_att; - for (i = 0; i < index->rd_att->natts; i++) + /* + * The truncated tupdesc for non-leaf index tuples, which doesn't contain + * the INCLUDE attributes. + * + * It is used to form tuples during tuple adjustement and page split. + * B-tree creates shortened tuple descriptor for every truncated tuple, + * because it is doing this less often: it does not have to form truncated + * tuples during page split. Also, B-tree is not adjusting tuples on + * internal pages the way GiST does. + */ + giststate->nonLeafTupdesc = CreateTupleDescCopyConstr(index->rd_att); + giststate->nonLeafTupdesc->natts = + IndexRelationGetNumberOfKeyAttributes(index); + + for (i = 0; i < IndexRelationGetNumberOfKeyAttributes(index); i++) { fmgr_info_copy(&(giststate->consistentFn[i]), index_getprocinfo(index, i + 1, GIST_CONSISTENT_PROC), @@ -1531,6 +1547,21 @@ initGISTstate(Relation index) giststate->supportCollation[i] = DEFAULT_COLLATION_OID; } + /* No opclass information for INCLUDE attributes */ + for (; i < index->rd_att->natts; i++) + { + giststate->consistentFn[i].fn_oid = InvalidOid; + giststate->unionFn[i].fn_oid = InvalidOid; + giststate->compressFn[i].fn_oid = InvalidOid; + giststate->decompressFn[i].fn_oid = InvalidOid; + giststate->penaltyFn[i].fn_oid = InvalidOid; + giststate->picksplitFn[i].fn_oid = InvalidOid; + giststate->equalFn[i].fn_oid = InvalidOid; + giststate->distanceFn[i].fn_oid = InvalidOid; + giststate->fetchFn[i].fn_oid = InvalidOid; + giststate->supportCollation[i] = InvalidOid; + } + MemoryContextSwitchTo(oldCxt); return giststate; -- cgit v1.2.3