diff options
Diffstat (limited to 'src/backend/access/gist')
-rw-r--r-- | src/backend/access/gist/gistget.c | 71 | ||||
-rw-r--r-- | src/backend/access/gist/gistscan.c | 75 |
2 files changed, 33 insertions, 113 deletions
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index 7a8692b5087..e5eb6f66a49 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -18,6 +18,7 @@ #include "access/relscan.h" #include "miscadmin.h" #include "pgstat.h" +#include "lib/pairingheap.h" #include "utils/builtins.h" #include "utils/memutils.h" #include "utils/rel.h" @@ -243,8 +244,6 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances, GISTPageOpaque opaque; OffsetNumber maxoff; OffsetNumber i; - GISTSearchTreeItem *tmpItem = so->tmpTreeItem; - bool isNew; MemoryContext oldcxt; Assert(!GISTSearchItemIsHeap(*pageItem)); @@ -275,18 +274,15 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances, oldcxt = MemoryContextSwitchTo(so->queueCxt); /* Create new GISTSearchItem for the right sibling index page */ - item = palloc(sizeof(GISTSearchItem)); - item->next = NULL; + item = palloc(SizeOfGISTSearchItem(scan->numberOfOrderBys)); item->blkno = opaque->rightlink; item->data.parentlsn = pageItem->data.parentlsn; /* Insert it into the queue using same distances as for this page */ - tmpItem->head = item; - tmpItem->lastHeap = NULL; - memcpy(tmpItem->distances, myDistances, + memcpy(item->distances, myDistances, sizeof(double) * scan->numberOfOrderBys); - (void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew); + pairingheap_add(so->queue, &item->phNode); MemoryContextSwitchTo(oldcxt); } @@ -348,8 +344,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances, oldcxt = MemoryContextSwitchTo(so->queueCxt); /* Create new GISTSearchItem for this item */ - item = palloc(sizeof(GISTSearchItem)); - item->next = NULL; + item = palloc(SizeOfGISTSearchItem(scan->numberOfOrderBys)); if (GistPageIsLeaf(page)) { @@ -372,12 +367,10 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances, } /* Insert it into the queue using new distance data */ - tmpItem->head = item; - tmpItem->lastHeap = GISTSearchItemIsHeap(*item) ? item : NULL; - memcpy(tmpItem->distances, so->distances, + memcpy(item->distances, so->distances, sizeof(double) * scan->numberOfOrderBys); - (void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew); + pairingheap_add(so->queue, &item->phNode); MemoryContextSwitchTo(oldcxt); } @@ -390,44 +383,24 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances, * Extract next item (in order) from search queue * * Returns a GISTSearchItem or NULL. Caller must pfree item when done with it. - * - * NOTE: on successful return, so->curTreeItem is the GISTSearchTreeItem that - * contained the result item. Callers can use so->curTreeItem->distances as - * the distances value for the item. */ static GISTSearchItem * getNextGISTSearchItem(GISTScanOpaque so) { - for (;;) - { - GISTSearchItem *item; - - /* Update curTreeItem if we don't have one */ - if (so->curTreeItem == NULL) - { - so->curTreeItem = (GISTSearchTreeItem *) rb_leftmost(so->queue); - /* Done when tree is empty */ - if (so->curTreeItem == NULL) - break; - } + GISTSearchItem *item; - item = so->curTreeItem->head; - if (item != NULL) - { - /* Delink item from chain */ - so->curTreeItem->head = item->next; - if (item == so->curTreeItem->lastHeap) - so->curTreeItem->lastHeap = NULL; - /* Return item; caller is responsible to pfree it */ - return item; - } - - /* curTreeItem is exhausted, so remove it from rbtree */ - rb_delete(so->queue, (RBNode *) so->curTreeItem); - so->curTreeItem = NULL; + if (!pairingheap_is_empty(so->queue)) + { + item = (GISTSearchItem *) pairingheap_remove_first(so->queue); + } + else + { + /* Done when both heaps are empty */ + item = NULL; } - return NULL; + /* Return item; caller is responsible to pfree it */ + return item; } /* @@ -458,7 +431,7 @@ getNextNearest(IndexScanDesc scan) /* visit an index page, extract its items into queue */ CHECK_FOR_INTERRUPTS(); - gistScanPage(scan, item, so->curTreeItem->distances, NULL, NULL); + gistScanPage(scan, item, item->distances, NULL, NULL); } pfree(item); @@ -491,7 +464,6 @@ gistgettuple(PG_FUNCTION_ARGS) pgstat_count_index_scan(scan->indexRelation); so->firstCall = false; - so->curTreeItem = NULL; so->curPageData = so->nPageData = 0; fakeItem.blkno = GIST_ROOT_BLKNO; @@ -534,7 +506,7 @@ gistgettuple(PG_FUNCTION_ARGS) * this page, we fall out of the inner "do" and loop around to * return them. */ - gistScanPage(scan, item, so->curTreeItem->distances, NULL, NULL); + gistScanPage(scan, item, item->distances, NULL, NULL); pfree(item); } while (so->nPageData == 0); @@ -560,7 +532,6 @@ gistgetbitmap(PG_FUNCTION_ARGS) pgstat_count_index_scan(scan->indexRelation); /* Begin the scan by processing the root page */ - so->curTreeItem = NULL; so->curPageData = so->nPageData = 0; fakeItem.blkno = GIST_ROOT_BLKNO; @@ -580,7 +551,7 @@ gistgetbitmap(PG_FUNCTION_ARGS) CHECK_FOR_INTERRUPTS(); - gistScanPage(scan, item, so->curTreeItem->distances, tbm, &ntids); + gistScanPage(scan, item, item->distances, tbm, &ntids); pfree(item); } diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c index 8360b16ae50..eff02c4dbde 100644 --- a/src/backend/access/gist/gistscan.c +++ b/src/backend/access/gist/gistscan.c @@ -22,14 +22,13 @@ /* - * RBTree support functions for the GISTSearchTreeItem queue + * Pairing heap comparison function for the GISTSearchItem queue */ - static int -GISTSearchTreeItemComparator(const RBNode *a, const RBNode *b, void *arg) +pairingheap_GISTSearchItem_cmp(const pairingheap_node *a, const pairingheap_node *b, void *arg) { - const GISTSearchTreeItem *sa = (const GISTSearchTreeItem *) a; - const GISTSearchTreeItem *sb = (const GISTSearchTreeItem *) b; + const GISTSearchItem *sa = (const GISTSearchItem *) a; + const GISTSearchItem *sb = (const GISTSearchItem *) b; IndexScanDesc scan = (IndexScanDesc) arg; int i; @@ -37,59 +36,16 @@ GISTSearchTreeItemComparator(const RBNode *a, const RBNode *b, void *arg) for (i = 0; i < scan->numberOfOrderBys; i++) { if (sa->distances[i] != sb->distances[i]) - return (sa->distances[i] > sb->distances[i]) ? 1 : -1; - } - - return 0; -} - -static void -GISTSearchTreeItemCombiner(RBNode *existing, const RBNode *newrb, void *arg) -{ - GISTSearchTreeItem *scurrent = (GISTSearchTreeItem *) existing; - const GISTSearchTreeItem *snew = (const GISTSearchTreeItem *) newrb; - GISTSearchItem *newitem = snew->head; - - /* snew should have just one item in its chain */ - Assert(newitem && newitem->next == NULL); - - /* - * If new item is heap tuple, it goes to front of chain; otherwise insert - * it before the first index-page item, so that index pages are visited in - * LIFO order, ensuring depth-first search of index pages. See comments - * in gist_private.h. - */ - if (GISTSearchItemIsHeap(*newitem)) - { - newitem->next = scurrent->head; - scurrent->head = newitem; - if (scurrent->lastHeap == NULL) - scurrent->lastHeap = newitem; + return (sa->distances[i] < sb->distances[i]) ? 1 : -1; } - else if (scurrent->lastHeap == NULL) - { - newitem->next = scurrent->head; - scurrent->head = newitem; - } - else - { - newitem->next = scurrent->lastHeap->next; - scurrent->lastHeap->next = newitem; - } -} -static RBNode * -GISTSearchTreeItemAllocator(void *arg) -{ - IndexScanDesc scan = (IndexScanDesc) arg; - - return palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys); -} + /* Heap items go before inner pages, to ensure a depth-first search */ + if (GISTSearchItemIsHeap(*sa) && !GISTSearchItemIsHeap(*sb)) + return -1; + if (!GISTSearchItemIsHeap(*sa) && GISTSearchItemIsHeap(*sb)) + return 1; -static void -GISTSearchTreeItemDeleter(RBNode *rb, void *arg) -{ - pfree(rb); + return 0; } @@ -127,7 +83,6 @@ gistbeginscan(PG_FUNCTION_ARGS) so->queueCxt = giststate->scanCxt; /* see gistrescan */ /* workspaces with size dependent on numberOfOrderBys: */ - so->tmpTreeItem = palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys); so->distances = palloc(sizeof(double) * scan->numberOfOrderBys); so->qual_ok = true; /* in case there are zero keys */ @@ -188,15 +143,9 @@ gistrescan(PG_FUNCTION_ARGS) /* create new, empty RBTree for search queue */ oldCxt = MemoryContextSwitchTo(so->queueCxt); - so->queue = rb_create(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys, - GISTSearchTreeItemComparator, - GISTSearchTreeItemCombiner, - GISTSearchTreeItemAllocator, - GISTSearchTreeItemDeleter, - scan); + so->queue = pairingheap_allocate(pairingheap_GISTSearchItem_cmp, scan); MemoryContextSwitchTo(oldCxt); - so->curTreeItem = NULL; so->firstCall = true; /* Update scan key, if a new one is given */ |