Skip to content

Commit 25b1daf

Browse files
committed
Further optimize multi-key GIN searches.
If we're skipping past a certain TID, avoid decoding posting list segments that only contain smaller TIDs. Extracted from Alexander Korotkov's fast scan patch, heavily modified.
1 parent e20c70c commit 25b1daf

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

src/backend/access/gin/gindatapage.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,19 +96,49 @@ static void dataPlaceToPageLeafSplit(Buffer buf,
9696
XLogRecData **prdata, Page lpage, Page rpage);
9797

9898
/*
99-
* Read all TIDs from leaf data page to single uncompressed array.
99+
* Read TIDs from leaf data page to single uncompressed array. The TIDs are
100+
* returned in ascending order.
101+
*
102+
* advancePast is a hint, indicating that the caller is only interested in
103+
* TIDs > advancePast. To return all items, use ItemPointerSetMin.
104+
*
105+
* Note: This function can still return items smaller than advancePast that
106+
* are in the same posting list as the items of interest, so the caller must
107+
* still check all the returned items. But passing it allows this function to
108+
* skip whole posting lists.
100109
*/
101110
ItemPointer
102-
GinDataLeafPageGetItems(Page page, int *nitems)
111+
GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast)
103112
{
104113
ItemPointer result;
105114

106115
if (GinPageIsCompressed(page))
107116
{
108-
GinPostingList *ptr = GinDataLeafPageGetPostingList(page);
117+
GinPostingList *seg = GinDataLeafPageGetPostingList(page);
109118
Size len = GinDataLeafPageGetPostingListSize(page);
119+
Pointer endptr = ((Pointer) seg) + len;
120+
GinPostingList *next;
121+
122+
/* Skip to the segment containing advancePast+1 */
123+
if (ItemPointerIsValid(&advancePast))
124+
{
125+
next = GinNextPostingListSegment(seg);
126+
while ((Pointer) next < endptr &&
127+
ginCompareItemPointers(&next->first, &advancePast) <= 0)
128+
{
129+
seg = next;
130+
next = GinNextPostingListSegment(seg);
131+
}
132+
len = endptr - (Pointer) seg;
133+
}
110134

111-
result = ginPostingListDecodeAllSegments(ptr, len, nitems);
135+
if (len > 0)
136+
result = ginPostingListDecodeAllSegments(seg, len, nitems);
137+
else
138+
{
139+
result = NULL;
140+
*nitems = 0;
141+
}
112142
}
113143
else
114144
{

src/backend/access/gin/ginget.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ startScanEntry(GinState *ginstate, GinScanEntry entry)
400400
BlockNumber rootPostingTree = GinGetPostingTree(itup);
401401
GinBtreeStack *stack;
402402
Page page;
403+
ItemPointerData minItem;
403404

404405
/*
405406
* We should unlock entry page before touching posting tree to
@@ -426,7 +427,8 @@ startScanEntry(GinState *ginstate, GinScanEntry entry)
426427
/*
427428
* Load the first page into memory.
428429
*/
429-
entry->list = GinDataLeafPageGetItems(page, &entry->nlist);
430+
ItemPointerSetMin(&minItem);
431+
entry->list = GinDataLeafPageGetItems(page, &entry->nlist, minItem);
430432

431433
entry->predictNumberResult = stack->predictNumber * entry->nlist;
432434

@@ -558,7 +560,7 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry, ItemPointerData advan
558560
continue;
559561
}
560562

561-
entry->list = GinDataLeafPageGetItems(page, &entry->nlist);
563+
entry->list = GinDataLeafPageGetItems(page, &entry->nlist, advancePast);
562564

563565
for (i = 0; i < entry->nlist; i++)
564566
{

src/include/access/gin_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ extern ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum,
692692
IndexTuple itup, int *nitems);
693693

694694
/* gindatapage.c */
695-
extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems);
695+
extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast);
696696
extern int GinDataLeafPageGetItemsToTbm(Page page, TIDBitmap *tbm);
697697
extern BlockNumber createPostingTree(Relation index,
698698
ItemPointerData *items, uint32 nitems,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy