Index-only scans for GIST
Hi, hackers!
There are first results of my work on GSoC project "Index-only scans for
GIST".
1. Version of my project code is in forked repository
https://github.com/lubennikovaav/postgres/tree/indexonlygist2
Patch is in attachments
- This version is only for one-column indexes
- fetch() method is realized only for box opclass (because it's trivial)
2. I test Index-only scans with SQL script box_test.sql
and it works really faster. (results in box_test_out)
I'll be glad to get your feedback about this feature.
--
Best regards,
Lubennikova Anastasia
Attachments:
indexonlygist_2.0.patchapplication/octet-stream; name=indexonlygist_2.0.patchDownload
*** a/src/backend/access/gist/gist.c
--- b/src/backend/access/gist/gist.c
***************
*** 1379,1384 **** initGISTstate(Relation index)
--- 1379,1399 ----
else
giststate->distanceFn[i].fn_oid = InvalidOid;
+ /* opclasses are not required to provide a Fetch method */
+ if (i<1) //for Debugging. Singlecolumn index
+ {
+ //elog(NOTICE, "Debug. gist.c amsupport = %d", index->rd_am->amsupport);
+ //elog(NOTICE, "Debug. gist.c OidIsValid. fetch. rd_support(%d) = %d", GIST_FETCH_PROC, index->rd_support[GIST_FETCH_PROC-1]);
+ if (OidIsValid(index_getprocid(index, i + 1, GIST_FETCH_PROC))) {
+ fmgr_info_copy(&(giststate->fetchFn[i]),
+ index_getprocinfo(index, i + 1, GIST_FETCH_PROC),
+ scanCxt);
+ }
+ else {
+ giststate->fetchFn[i].fn_oid = InvalidOid;
+ }
+ }
+
/*
* If the index column has a specified collation, we should honor that
* while doing comparisons. However, we may have a collatable storage
***************
*** 1401,1406 **** initGISTstate(Relation index)
--- 1416,1451 ----
return giststate;
}
+ Datum
+ gistcanreturn(PG_FUNCTION_ARGS) {
+ int i;
+ Relation index = (Relation) PG_GETARG_POINTER(0);
+
+ for (i = 0; i < 1; i++) { //Singlecolumn
+
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. decompress. rd_support(%d) = %d", GIST_DECOMPRESS_PROC, index->rd_support[GIST_DECOMPRESS_PROC]);
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. distance. rd_support(%d) = %d", GIST_DISTANCE_PROC, index->rd_support[GIST_DISTANCE_PROC]);
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. fetch. rd_support(%d) = %d", GIST_FETCH_PROC, index->rd_support[GIST_FETCH_PROC]);
+
+ //Debug. singlecolumn index ==> second argument = ???
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. GIST_FETCH_PROC = %d", OidIsValid(index_getprocid(index, 0, GIST_FETCH_PROC)));
+ if (OidIsValid(index_getprocid(index, i+1, GIST_FETCH_PROC))) {
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. True");
+ PG_RETURN_BOOL(true);
+ }
+ else {
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. False");
+ //elog(NOTICE, " Debug. missing support function %d of index \"%s\"",
+ // GIST_FETCH_PROC,
+ //RelationGetRelationName(index));
+ PG_RETURN_BOOL(false);
+
+ }
+ }
+ //elog(NOTICE, "Debug. gist.c gistcanreturn. False. Multicolumn");
+ PG_RETURN_BOOL(false);
+ }
+
void
freeGISTstate(GISTSTATE *giststate)
{
*** a/src/backend/access/gist/gistget.c
--- b/src/backend/access/gist/gistget.c
***************
*** 240,245 **** gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
--- 240,249 ----
GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
Buffer buffer;
Page page;
+ GISTSTATE *giststate = so->giststate;
+ Relation r = scan->indexRelation;
+ bool isnull[INDEX_MAX_KEYS];
+ GISTSearchHeapItem *tmpListItem;
GISTPageOpaque opaque;
OffsetNumber maxoff;
OffsetNumber i;
***************
*** 288,297 **** gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
MemoryContextSwitchTo(oldcxt);
}
! so->nPageData = so->curPageData = 0;
/*
* check all tuples on page
--- 292,303 ----
(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
+ /* Create new GISTSearchHeapItem to insert into pageData*/
+
MemoryContextSwitchTo(oldcxt);
}
! so->curPageData = NULL;
/*
* check all tuples on page
***************
*** 329,340 **** gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
}
else if (scan->numberOfOrderBys == 0 && GistPageIsLeaf(page))
{
! /*
! * Non-ordered scan, so report heap tuples in so->pageData[]
! */
! so->pageData[so->nPageData].heapPtr = it->t_tid;
! so->pageData[so->nPageData].recheck = recheck;
! so->nPageData++;
}
else
{
--- 335,356 ----
}
else if (scan->numberOfOrderBys == 0 && GistPageIsLeaf(page))
{
! /* Non-oredered scan, so tuples report in so->pageData */
! oldcxt = MemoryContextSwitchTo(so->queueCxt);
! /* form tmpListItem and fill it with data to add into so->pageData */
! tmpListItem = palloc(sizeof(GISTSearchHeapItem));
! tmpListItem->heapPtr = it->t_tid;
! tmpListItem->recheck = recheck;
! if (scan->xs_want_itup)
! tmpListItem->ftup = gistFetchTuple(giststate, r, it, isnull);
!
! so->pageData = lappend(so->pageData, tmpListItem);
!
! /* If it's first call of lappend() we should set so->curPageData not NULL*/
! if(so->curPageData == NULL)
! so->curPageData = list_head(so->pageData);
!
! MemoryContextSwitchTo(oldcxt);
}
else
{
***************
*** 357,362 **** gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
--- 373,380 ----
item->blkno = InvalidBlockNumber;
item->data.heap.heapPtr = it->t_tid;
item->data.heap.recheck = recheck;
+ if (scan->xs_want_itup)
+ item->data.heap.ftup = gistFetchTuple(giststate, r, it, isnull);
}
else
{
***************
*** 451,456 **** getNextNearest(IndexScanDesc scan)
--- 469,476 ----
/* found a heap item at currently minimal distance */
scan->xs_ctup.t_self = item->data.heap.heapPtr;
scan->xs_recheck = item->data.heap.recheck;
+ if(scan->xs_want_itup)
+ scan->xs_itup = item->data.heap.ftup;
res = true;
}
else
***************
*** 492,498 **** gistgettuple(PG_FUNCTION_ARGS)
so->firstCall = false;
so->curTreeItem = NULL;
! so->curPageData = so->nPageData = 0;
fakeItem.blkno = GIST_ROOT_BLKNO;
memset(&fakeItem.data.parentlsn, 0, sizeof(GistNSN));
--- 512,519 ----
so->firstCall = false;
so->curTreeItem = NULL;
!
! so->curPageData = NULL;
fakeItem.blkno = GIST_ROOT_BLKNO;
memset(&fakeItem.data.parentlsn, 0, sizeof(GistNSN));
***************
*** 509,521 **** gistgettuple(PG_FUNCTION_ARGS)
/* Fetch tuples index-page-at-a-time */
for (;;)
{
! if (so->curPageData < so->nPageData)
! {
! /* continuing to return tuples from a leaf page */
! scan->xs_ctup.t_self = so->pageData[so->curPageData].heapPtr;
! scan->xs_recheck = so->pageData[so->curPageData].recheck;
! so->curPageData++;
! PG_RETURN_BOOL(true);
}
/* find and process the next index page */
--- 530,550 ----
/* Fetch tuples index-page-at-a-time */
for (;;)
{
! if(so->curPageData!=NULL) {
! GISTSearchHeapItem *tmp = (GISTSearchHeapItem *)lfirst(so->curPageData);
! scan->xs_ctup.t_self = tmp->heapPtr;
! scan->xs_recheck = tmp->recheck;
! if(scan->xs_want_itup)
! scan->xs_itup = tmp->ftup;
!
! ListCell *tmpPageData = so->curPageData;
! /* go to next ListCell */
! so->curPageData = lnext(so->curPageData);
! /* Delete ListCell that we have already read.
! * It's always head of so->pageData
! */
! so->pageData = list_delete_cell(so->pageData, tmpPageData, NULL);
! PG_RETURN_BOOL(TRUE);
}
/* find and process the next index page */
***************
*** 537,543 **** gistgettuple(PG_FUNCTION_ARGS)
gistScanPage(scan, item, so->curTreeItem->distances, NULL, NULL);
pfree(item);
! } while (so->nPageData == 0);
}
}
}
--- 566,572 ----
gistScanPage(scan, item, so->curTreeItem->distances, NULL, NULL);
pfree(item);
! } while (list_length(so->pageData)==0);
}
}
}
***************
*** 561,567 **** gistgetbitmap(PG_FUNCTION_ARGS)
/* Begin the scan by processing the root page */
so->curTreeItem = NULL;
! so->curPageData = so->nPageData = 0;
fakeItem.blkno = GIST_ROOT_BLKNO;
memset(&fakeItem.data.parentlsn, 0, sizeof(GistNSN));
--- 590,597 ----
/* Begin the scan by processing the root page */
so->curTreeItem = NULL;
! so->curPageData = NULL;
! //so->curPageData = so->nPageData = 0;
fakeItem.blkno = GIST_ROOT_BLKNO;
memset(&fakeItem.data.parentlsn, 0, sizeof(GistNSN));
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
***************
*** 152,157 **** gist_box_decompress(PG_FUNCTION_ARGS)
--- 152,168 ----
}
/*
+ * GiST Fetch method for boxes
+ * do not do anything --- we just use the stored box as is.
+ */
+ Datum
+ gist_box_fetch(PG_FUNCTION_ARGS)
+ {
+ //elog(NOTICE, "Debug. gistproc.c we are in gist_box_fetch");
+ PG_RETURN_POINTER(PG_GETARG_POINTER(0));
+ }
+
+ /*
* The GiST Penalty method for boxes (also used for points)
*
* As in the R-tree paper, we use change in area as our penalty metric
*** a/src/backend/access/gist/gistscan.c
--- b/src/backend/access/gist/gistscan.c
***************
*** 133,138 **** gistbeginscan(PG_FUNCTION_ARGS)
--- 133,146 ----
scan->opaque = so;
+ /* All fields required for index-only scans are null until gistrescan.
+ * However, we set up scan->xs_itupdesc whether we'll need it or not,
+ * since that's cheap.
+ */
+ so->pageData = NULL;
+ so->curPageData = NULL;
+ scan->xs_itupdesc = RelationGetDescr(r);
+
MemoryContextSwitchTo(oldCxt);
PG_RETURN_POINTER(scan);
***************
*** 194,204 **** gistrescan(PG_FUNCTION_ARGS)
GISTSearchTreeItemAllocator,
GISTSearchTreeItemDeleter,
scan);
MemoryContextSwitchTo(oldCxt);
- so->curTreeItem = NULL;
so->firstCall = true;
!
/* Update scan key, if a new one is given */
if (key && scan->numberOfKeys > 0)
{
--- 202,212 ----
GISTSearchTreeItemAllocator,
GISTSearchTreeItemDeleter,
scan);
+
MemoryContextSwitchTo(oldCxt);
so->firstCall = true;
!
/* Update scan key, if a new one is given */
if (key && scan->numberOfKeys > 0)
{
*** a/src/backend/access/gist/gistutil.c
--- b/src/backend/access/gist/gistutil.c
***************
*** 618,623 **** gistFormTuple(GISTSTATE *giststate, Relation r,
--- 618,684 ----
return res;
}
+
+ /*
+ * initialize a GiST entry with fetched value in key field
+ */
+ void
+ gistfentryinit(GISTSTATE *giststate, int nkey,
+ GISTENTRY *e, Datum k, Relation r,
+ Page pg, OffsetNumber o, bool l, bool isNull)
+ {
+ if (!isNull)
+ {
+ GISTENTRY *fep;
+
+ gistentryinit(*e, k, r, pg, o, l);
+ fep = (GISTENTRY *)
+ DatumGetPointer(FunctionCall1Coll(&giststate->fetchFn[nkey],
+ giststate->supportCollation[nkey],
+ PointerGetDatum(e)));
+ //elog(NOTICE, "Debug. gistfentryinit()");
+ /* fecthFn returns the given pointer */
+ if (fep != e)
+ gistentryinit(*e, fep->key, fep->rel, fep->page, fep->offset,
+ fep->leafkey);
+ }
+ else
+ gistentryinit(*e, (Datum) 0, r, pg, o, l);
+ }
+
+ /*
+ * Fetch all keys in tuple --TODO
+ * Now it works only for single column indexes
+ * returns new IndexTuple that contains GISTENTRY with fetched data in key field
+ */
+ IndexTuple
+ gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple, bool isnull[])
+ {
+ GISTENTRY fentry[INDEX_MAX_KEYS];
+ Datum fetchatt[INDEX_MAX_KEYS];
+ int i;
+ IndexTuple res;
+
+ for (i = 0; i < 1; i++) { // Singlecolumn
+
+ Datum datum = index_getattr(tuple, i + 1, giststate->tupdesc, &isnull[i]);
+
+ gistfentryinit(giststate, i, &fentry[i],
+ datum, r, NULL, (OffsetNumber) 0,
+ FALSE, FALSE);
+ fetchatt[i] = fentry[i].key;
+ }
+ //elog(NOTICE, "Debug. gistFetchTuple. Before index_form_tuple");
+ res = index_form_tuple(giststate->tupdesc, fetchatt, isnull);
+
+ /*
+ * The offset number on tuples on internal pages is unused. For historical
+ * reasons, it is set 0xffff.
+ */
+ ItemPointerSetOffsetNumber(&(res->t_tid), 0xffff);
+ return res;
+ }
+
float
gistpenalty(GISTSTATE *giststate, int attno,
GISTENTRY *orig, bool isNullOrig,
*** a/src/include/access/gist.h
--- b/src/include/access/gist.h
***************
*** 33,39 ****
#define GIST_PICKSPLIT_PROC 6
#define GIST_EQUAL_PROC 7
#define GIST_DISTANCE_PROC 8
! #define GISTNProcs 8
/*
* strategy numbers for GiST opclasses that want to implement the old
--- 33,40 ----
#define GIST_PICKSPLIT_PROC 6
#define GIST_EQUAL_PROC 7
#define GIST_DISTANCE_PROC 8
! #define GIST_FETCH_PROC 9
! #define GISTNProcs 9
/*
* strategy numbers for GiST opclasses that want to implement the old
*** a/src/include/access/gist_private.h
--- b/src/include/access/gist_private.h
***************
*** 86,91 **** typedef struct GISTSTATE
--- 86,92 ----
FmgrInfo picksplitFn[INDEX_MAX_KEYS];
FmgrInfo equalFn[INDEX_MAX_KEYS];
FmgrInfo distanceFn[INDEX_MAX_KEYS];
+ FmgrInfo fetchFn[INDEX_MAX_KEYS];
/* Collations to pass to the support functions */
Oid supportCollation[INDEX_MAX_KEYS];
***************
*** 117,122 **** typedef struct GISTSearchHeapItem
--- 118,124 ----
{
ItemPointerData heapPtr;
bool recheck; /* T if quals must be rechecked */
+ IndexTuple ftup; /* Tuple contains datum fetched from key for index-only scans. ftup = fetched tuple*/
} GISTSearchHeapItem;
/* Unvisited item, either index page or heap tuple */
***************
*** 167,175 **** typedef struct GISTScanOpaqueData
double *distances; /* output area for gistindex_keytest */
/* In a non-ordered search, returnable heap items are stored here: */
! GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
! OffsetNumber nPageData; /* number of valid items in array */
! OffsetNumber curPageData; /* next item to return */
} GISTScanOpaqueData;
typedef GISTScanOpaqueData *GISTScanOpaque;
--- 169,177 ----
double *distances; /* output area for gistindex_keytest */
/* In a non-ordered search, returnable heap items are stored here: */
! List *pageData;
! ListCell *curPageData;
!
} GISTScanOpaqueData;
typedef GISTScanOpaqueData *GISTScanOpaque;
***************
*** 423,428 **** typedef struct GiSTOptions
--- 425,431 ----
/* gist.c */
extern Datum gistbuildempty(PG_FUNCTION_ARGS);
extern Datum gistinsert(PG_FUNCTION_ARGS);
+ extern Datum gistcanreturn(PG_FUNCTION_ARGS);
extern MemoryContext createTempGistContext(void);
extern GISTSTATE *initGISTstate(Relation index);
extern void freeGISTstate(GISTSTATE *giststate);
***************
*** 522,527 **** extern bool gistKeyIsEQ(GISTSTATE *giststate, int attno, Datum a, Datum b);
--- 525,536 ----
extern void gistDeCompressAtt(GISTSTATE *giststate, Relation r, IndexTuple tuple, Page p,
OffsetNumber o, GISTENTRY *attdata, bool *isnull);
+ extern void gistfentryinit(GISTSTATE *giststate, int nkey,
+ GISTENTRY *e, Datum k, Relation r,
+ Page pg, OffsetNumber o, bool l, bool isNull);
+
+ extern IndexTuple gistFetchTuple(GISTSTATE *giststate, Relation r, IndexTuple tuple, bool *isnull);
+
extern void gistMakeUnionKey(GISTSTATE *giststate, int attno,
GISTENTRY *entry1, bool isnull1,
GISTENTRY *entry2, bool isnull2,
*** a/src/include/catalog/pg_am.h
--- b/src/include/catalog/pg_am.h
***************
*** 123,129 **** DESCR("b-tree index access method");
DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup - hashcostestimate hashoptions ));
DESCR("hash index access method");
#define HASH_AM_OID 405
! DATA(insert OID = 783 ( gist 0 8 f t f f t t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup - gistcostestimate gistoptions ));
DESCR("GiST index access method");
#define GIST_AM_OID 783
DATA(insert OID = 2742 ( gin 0 6 f f f f t t f f t f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions ));
--- 123,129 ----
DATA(insert OID = 405 ( hash 1 1 f f t f f f f f f f f 23 hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbuildempty hashbulkdelete hashvacuumcleanup - hashcostestimate hashoptions ));
DESCR("hash index access method");
#define HASH_AM_OID 405
! DATA(insert OID = 783 ( gist 0 9 f t f f t t f t t t f 0 gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbuildempty gistbulkdelete gistvacuumcleanup gistcanreturn gistcostestimate gistoptions ));
DESCR("GiST index access method");
#define GIST_AM_OID 783
DATA(insert OID = 2742 ( gin 0 6 f f f f t t f f t f f 0 gininsert ginbeginscan - gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbuildempty ginbulkdelete ginvacuumcleanup - gincostestimate ginoptions ));
*** a/src/include/catalog/pg_amproc.h
--- b/src/include/catalog/pg_amproc.h
***************
*** 195,200 **** DATA(insert ( 2593 603 603 4 2580 ));
--- 195,201 ----
DATA(insert ( 2593 603 603 5 2581 ));
DATA(insert ( 2593 603 603 6 2582 ));
DATA(insert ( 2593 603 603 7 2584 ));
+ DATA(insert ( 2593 603 603 9 3252 ));
DATA(insert ( 2594 604 604 1 2585 ));
DATA(insert ( 2594 604 604 2 2583 ));
DATA(insert ( 2594 604 604 3 2586 ));
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 941,946 **** DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 1 0 0 0 f f f f t f v
--- 941,949 ----
DESCR("gist(internal)");
DATA(insert OID = 2561 ( gistvacuumcleanup PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ gistvacuumcleanup _null_ _null_ _null_ ));
DESCR("gist(internal)");
+ //Debug
+ DATA(insert OID = 3251 ( gistcanreturn PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 16 "2281" _null_ _null_ _null_ _null_ gistcanreturn _null_ _null_ _null_ ));
+ DESCR("gist(internal)");
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 1 0 0 0 f f f f t f v 7 0 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ _null_ gistcostestimate _null_ _null_ _null_ ));
DESCR("gist(internal)");
DATA(insert OID = 2787 ( gistoptions PGNSP PGUID 12 1 0 0 0 f f f f t f s 2 0 17 "1009 16" _null_ _null_ _null_ _null_ gistoptions _null_ _null_ _null_ ));
***************
*** 3996,4001 **** DATA(insert OID = 2579 ( gist_box_compress PGNSP PGUID 12 1 0 0 0 f f f f t f
--- 3999,4007 ----
DESCR("GiST support");
DATA(insert OID = 2580 ( gist_box_decompress PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_box_decompress _null_ _null_ _null_ ));
DESCR("GiST support");
+ //Debug. gist_box_fetch
+ DATA(insert OID = 3252 ( gist_box_fetch PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_box_fetch _null_ _null_ _null_ ));
+ DESCR("GiST support");
DATA(insert OID = 2581 ( gist_box_penalty PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 2281 "2281 2281 2281" _null_ _null_ _null_ _null_ gist_box_penalty _null_ _null_ _null_ ));
DESCR("GiST support");
DATA(insert OID = 2582 ( gist_box_picksplit PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 2281 "2281 2281" _null_ _null_ _null_ _null_ gist_box_picksplit _null_ _null_ _null_ ));
*** a/src/include/utils/geo_decls.h
--- b/src/include/utils/geo_decls.h
***************
*** 273,278 **** extern Datum box_out(PG_FUNCTION_ARGS);
--- 273,279 ----
extern Datum box_recv(PG_FUNCTION_ARGS);
extern Datum box_send(PG_FUNCTION_ARGS);
extern Datum box_same(PG_FUNCTION_ARGS);
+ extern Datum gist_box_fetch(PG_FUNCTION_ARGS); //Debug. gist_box_fetch
extern Datum box_overlap(PG_FUNCTION_ARGS);
extern Datum box_left(PG_FUNCTION_ARGS);
extern Datum box_overleft(PG_FUNCTION_ARGS);
On Sun, May 25, 2014 at 6:12 AM, Anastasia Lubennikova
<lubennikovaav@gmail.com> wrote:
Hi, hackers!
There are first results of my work on GSoC project "Index-only scans for
GIST".
Cool.
1. Version of my project code is in forked repository
https://github.com/lubennikovaav/postgres/tree/indexonlygist2
Patch is in attachments
- This version is only for one-column indexes
That's probably a limitation that needs to be fixed before this can be
committed.
- fetch() method is realized only for box opclass (because it's trivial)
That might not need to be fixed before this can be committed.
2. I test Index-only scans with SQL script box_test.sql
and it works really faster. (results in box_test_out)I'll be glad to get your feedback about this feature.
Since this is a GSoC project, it would be nice if one of the people
who is knowledgeable about GIST (Heikki, Alexander, etc.) could weigh
in on this before too much time goes by, so that Anastasia can press
forward with this work.
I don't know enough to offer too many substantive comments, but I
think you should remove all of the //-style comments (most of which
are debugging leftovers) and add some more comments describing what
you're actually doing and, more importantly, why.
This comment doesn't appear to make sense:
+ /*
+ * The offset number on tuples on internal pages is unused.
For historical
+ * reasons, it is set 0xffff.
+ */
The reason this doesn't make sense is because the tuple in question is
not on an internal page, or indeed any page at all.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers