mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									e20c70cb0f
								
							
						
					
					
						commit
						25b1dafab6
					
				@ -96,19 +96,49 @@ static void dataPlaceToPageLeafSplit(Buffer buf,
 | 
			
		||||
						 XLogRecData **prdata, Page lpage, Page rpage);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Read all TIDs from leaf data page to single uncompressed array.
 | 
			
		||||
 * Read TIDs from leaf data page to single uncompressed array. The TIDs are
 | 
			
		||||
 * returned in ascending order.
 | 
			
		||||
 *
 | 
			
		||||
 * advancePast is a hint, indicating that the caller is only interested in
 | 
			
		||||
 * TIDs > advancePast. To return all items, use ItemPointerSetMin.
 | 
			
		||||
 *
 | 
			
		||||
 * Note: This function can still return items smaller than advancePast that
 | 
			
		||||
 * are in the same posting list as the items of interest, so the caller must
 | 
			
		||||
 * still check all the returned items. But passing it allows this function to
 | 
			
		||||
 * skip whole posting lists.
 | 
			
		||||
 */
 | 
			
		||||
ItemPointer
 | 
			
		||||
GinDataLeafPageGetItems(Page page, int *nitems)
 | 
			
		||||
GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast)
 | 
			
		||||
{
 | 
			
		||||
	ItemPointer result;
 | 
			
		||||
 | 
			
		||||
	if (GinPageIsCompressed(page))
 | 
			
		||||
	{
 | 
			
		||||
		GinPostingList *ptr = GinDataLeafPageGetPostingList(page);
 | 
			
		||||
		GinPostingList *seg = GinDataLeafPageGetPostingList(page);
 | 
			
		||||
		Size		len = GinDataLeafPageGetPostingListSize(page);
 | 
			
		||||
		Pointer		endptr = ((Pointer) seg) + len;
 | 
			
		||||
		GinPostingList *next;
 | 
			
		||||
 | 
			
		||||
		result = ginPostingListDecodeAllSegments(ptr, len, nitems);
 | 
			
		||||
		/* Skip to the segment containing advancePast+1 */
 | 
			
		||||
		if (ItemPointerIsValid(&advancePast))
 | 
			
		||||
		{
 | 
			
		||||
			next = GinNextPostingListSegment(seg);
 | 
			
		||||
			while ((Pointer) next < endptr &&
 | 
			
		||||
				   ginCompareItemPointers(&next->first, &advancePast) <= 0)
 | 
			
		||||
			{
 | 
			
		||||
				seg = next;
 | 
			
		||||
				next = GinNextPostingListSegment(seg);
 | 
			
		||||
			}
 | 
			
		||||
			len = endptr - (Pointer) seg;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (len > 0)
 | 
			
		||||
			result = ginPostingListDecodeAllSegments(seg, len, nitems);
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			result = NULL;
 | 
			
		||||
			*nitems = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
 | 
			
		||||
@ -400,6 +400,7 @@ restartScanEntry:
 | 
			
		||||
			BlockNumber rootPostingTree = GinGetPostingTree(itup);
 | 
			
		||||
			GinBtreeStack *stack;
 | 
			
		||||
			Page		page;
 | 
			
		||||
			ItemPointerData minItem;
 | 
			
		||||
 | 
			
		||||
			/*
 | 
			
		||||
			 * We should unlock entry page before touching posting tree to
 | 
			
		||||
@ -426,7 +427,8 @@ restartScanEntry:
 | 
			
		||||
			/*
 | 
			
		||||
			 * Load the first page into memory.
 | 
			
		||||
			 */
 | 
			
		||||
			entry->list = GinDataLeafPageGetItems(page, &entry->nlist);
 | 
			
		||||
			ItemPointerSetMin(&minItem);
 | 
			
		||||
			entry->list = GinDataLeafPageGetItems(page, &entry->nlist, minItem);
 | 
			
		||||
 | 
			
		||||
			entry->predictNumberResult = stack->predictNumber * entry->nlist;
 | 
			
		||||
 | 
			
		||||
@ -558,7 +560,7 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry, ItemPointerData advan
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		entry->list = GinDataLeafPageGetItems(page, &entry->nlist);
 | 
			
		||||
		entry->list = GinDataLeafPageGetItems(page, &entry->nlist, advancePast);
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < entry->nlist; i++)
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
@ -692,7 +692,7 @@ extern ItemPointer ginReadTuple(GinState *ginstate, OffsetNumber attnum,
 | 
			
		||||
			 IndexTuple itup, int *nitems);
 | 
			
		||||
 | 
			
		||||
/* gindatapage.c */
 | 
			
		||||
extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems);
 | 
			
		||||
extern ItemPointer GinDataLeafPageGetItems(Page page, int *nitems, ItemPointerData advancePast);
 | 
			
		||||
extern int GinDataLeafPageGetItemsToTbm(Page page, TIDBitmap *tbm);
 | 
			
		||||
extern BlockNumber createPostingTree(Relation index,
 | 
			
		||||
				  ItemPointerData *items, uint32 nitems,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user