mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-24 01:29:19 +03:00 
			
		
		
		
	Maintain the pg_stat_user_indexes.idx_scan pgstat counter during
contrib/Bloom index scans.
Oversight in commit 9ee014fc, which added the Bloom index contrib
module.
Author: Masahiro Ikeda <ikedamsh@oss.nttdata.com>
Reviewed-By: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/c48839d881388ee401a01807c686004d@oss.nttdata.com
Backpatch: 13- (all supported branches).
		
	
		
			
				
	
	
		
			174 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*-------------------------------------------------------------------------
 | |
|  *
 | |
|  * blscan.c
 | |
|  *		Bloom index scan functions.
 | |
|  *
 | |
|  * Copyright (c) 2016-2020, PostgreSQL Global Development Group
 | |
|  *
 | |
|  * IDENTIFICATION
 | |
|  *	  contrib/bloom/blscan.c
 | |
|  *
 | |
|  *-------------------------------------------------------------------------
 | |
|  */
 | |
| #include "postgres.h"
 | |
| 
 | |
| #include "access/relscan.h"
 | |
| #include "bloom.h"
 | |
| #include "miscadmin.h"
 | |
| #include "pgstat.h"
 | |
| #include "storage/bufmgr.h"
 | |
| #include "storage/lmgr.h"
 | |
| #include "utils/memutils.h"
 | |
| #include "utils/rel.h"
 | |
| 
 | |
| /*
 | |
|  * Begin scan of bloom index.
 | |
|  */
 | |
| IndexScanDesc
 | |
| blbeginscan(Relation r, int nkeys, int norderbys)
 | |
| {
 | |
| 	IndexScanDesc scan;
 | |
| 	BloomScanOpaque so;
 | |
| 
 | |
| 	scan = RelationGetIndexScan(r, nkeys, norderbys);
 | |
| 
 | |
| 	so = (BloomScanOpaque) palloc(sizeof(BloomScanOpaqueData));
 | |
| 	initBloomState(&so->state, scan->indexRelation);
 | |
| 	so->sign = NULL;
 | |
| 
 | |
| 	scan->opaque = so;
 | |
| 
 | |
| 	return scan;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Rescan a bloom index.
 | |
|  */
 | |
| void
 | |
| blrescan(IndexScanDesc scan, ScanKey scankey, int nscankeys,
 | |
| 		 ScanKey orderbys, int norderbys)
 | |
| {
 | |
| 	BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
 | |
| 
 | |
| 	if (so->sign)
 | |
| 		pfree(so->sign);
 | |
| 	so->sign = NULL;
 | |
| 
 | |
| 	if (scankey && scan->numberOfKeys > 0)
 | |
| 	{
 | |
| 		memmove(scan->keyData, scankey,
 | |
| 				scan->numberOfKeys * sizeof(ScanKeyData));
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * End scan of bloom index.
 | |
|  */
 | |
| void
 | |
| blendscan(IndexScanDesc scan)
 | |
| {
 | |
| 	BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
 | |
| 
 | |
| 	if (so->sign)
 | |
| 		pfree(so->sign);
 | |
| 	so->sign = NULL;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Insert all matching tuples into a bitmap.
 | |
|  */
 | |
| int64
 | |
| blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)
 | |
| {
 | |
| 	int64		ntids = 0;
 | |
| 	BlockNumber blkno = BLOOM_HEAD_BLKNO,
 | |
| 				npages;
 | |
| 	int			i;
 | |
| 	BufferAccessStrategy bas;
 | |
| 	BloomScanOpaque so = (BloomScanOpaque) scan->opaque;
 | |
| 
 | |
| 	if (so->sign == NULL)
 | |
| 	{
 | |
| 		/* New search: have to calculate search signature */
 | |
| 		ScanKey		skey = scan->keyData;
 | |
| 
 | |
| 		so->sign = palloc0(sizeof(BloomSignatureWord) * so->state.opts.bloomLength);
 | |
| 
 | |
| 		for (i = 0; i < scan->numberOfKeys; i++)
 | |
| 		{
 | |
| 			/*
 | |
| 			 * Assume bloom-indexable operators to be strict, so nothing could
 | |
| 			 * be found for NULL key.
 | |
| 			 */
 | |
| 			if (skey->sk_flags & SK_ISNULL)
 | |
| 			{
 | |
| 				pfree(so->sign);
 | |
| 				so->sign = NULL;
 | |
| 				return 0;
 | |
| 			}
 | |
| 
 | |
| 			/* Add next value to the signature */
 | |
| 			signValue(&so->state, so->sign, skey->sk_argument,
 | |
| 					  skey->sk_attno - 1);
 | |
| 
 | |
| 			skey++;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/*
 | |
| 	 * We're going to read the whole index. This is why we use appropriate
 | |
| 	 * buffer access strategy.
 | |
| 	 */
 | |
| 	bas = GetAccessStrategy(BAS_BULKREAD);
 | |
| 	npages = RelationGetNumberOfBlocks(scan->indexRelation);
 | |
| 	pgstat_count_index_scan(scan->indexRelation);
 | |
| 
 | |
| 	for (blkno = BLOOM_HEAD_BLKNO; blkno < npages; blkno++)
 | |
| 	{
 | |
| 		Buffer		buffer;
 | |
| 		Page		page;
 | |
| 
 | |
| 		buffer = ReadBufferExtended(scan->indexRelation, MAIN_FORKNUM,
 | |
| 									blkno, RBM_NORMAL, bas);
 | |
| 
 | |
| 		LockBuffer(buffer, BUFFER_LOCK_SHARE);
 | |
| 		page = BufferGetPage(buffer);
 | |
| 		TestForOldSnapshot(scan->xs_snapshot, scan->indexRelation, page);
 | |
| 
 | |
| 		if (!PageIsNew(page) && !BloomPageIsDeleted(page))
 | |
| 		{
 | |
| 			OffsetNumber offset,
 | |
| 						maxOffset = BloomPageGetMaxOffset(page);
 | |
| 
 | |
| 			for (offset = 1; offset <= maxOffset; offset++)
 | |
| 			{
 | |
| 				BloomTuple *itup = BloomPageGetTuple(&so->state, page, offset);
 | |
| 				bool		res = true;
 | |
| 
 | |
| 				/* Check index signature with scan signature */
 | |
| 				for (i = 0; i < so->state.opts.bloomLength; i++)
 | |
| 				{
 | |
| 					if ((itup->sign[i] & so->sign[i]) != so->sign[i])
 | |
| 					{
 | |
| 						res = false;
 | |
| 						break;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				/* Add matching tuples to bitmap */
 | |
| 				if (res)
 | |
| 				{
 | |
| 					tbm_add_tuples(tbm, &itup->heapPtr, 1, true);
 | |
| 					ntids++;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		UnlockReleaseBuffer(buffer);
 | |
| 		CHECK_FOR_INTERRUPTS();
 | |
| 	}
 | |
| 	FreeAccessStrategy(bas);
 | |
| 
 | |
| 	return ntids;
 | |
| }
 |