Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 041b968

Browse files
committed
Use streaming I/O in ANALYZE.
The ANALYZE command prefetches and reads sample blocks chosen by a BlockSampler algorithm. Instead of calling [Prefetch|Read]Buffer() for each block, ANALYZE now uses the streaming API introduced in b5a9b18. Author: Nazir Bilal Yavuz <byavuz81@gmail.com> Reviewed-by: Melanie Plageman <melanieplageman@gmail.com> Reviewed-by: Andres Freund <andres@anarazel.de> Reviewed-by: Jakub Wartak <jakub.wartak@enterprisedb.com> Reviewed-by: Heikki Linnakangas <hlinnaka@iki.fi> Reviewed-by: Thomas Munro <thomas.munro@gmail.com> Discussion: https://postgr.es/m/flat/CAN55FZ0UhXqk9v3y-zW_fp4-WCp43V8y0A72xPmLkOM%2B6M%2BmJg%40mail.gmail.com
1 parent f587338 commit 041b968

File tree

3 files changed

+43
-76
lines changed

3 files changed

+43
-76
lines changed

src/backend/access/heap/heapam_handler.c

+16-13
Original file line numberDiff line numberDiff line change
@@ -1055,33 +1055,36 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
10551055
}
10561056

10571057
/*
1058-
* Prepare to analyze block `blockno` of `scan`. The scan has been started
1058+
* Prepare to analyze the next block in the read stream. Returns false if
1059+
* the stream is exhausted and true otherwise. The scan must have been started
10591060
* with SO_TYPE_ANALYZE option.
10601061
*
10611062
* This routine holds a buffer pin and lock on the heap page. They are held
10621063
* until heapam_scan_analyze_next_tuple() returns false. That is until all the
10631064
* items of the heap page are analyzed.
10641065
*/
1065-
void
1066-
heapam_scan_analyze_next_block(TableScanDesc scan, BlockNumber blockno,
1067-
BufferAccessStrategy bstrategy)
1066+
bool
1067+
heapam_scan_analyze_next_block(TableScanDesc scan, ReadStream *stream)
10681068
{
10691069
HeapScanDesc hscan = (HeapScanDesc) scan;
10701070

10711071
/*
10721072
* We must maintain a pin on the target page's buffer to ensure that
10731073
* concurrent activity - e.g. HOT pruning - doesn't delete tuples out from
1074-
* under us. Hence, pin the page until we are done looking at it. We
1075-
* also choose to hold sharelock on the buffer throughout --- we could
1076-
* release and re-acquire sharelock for each tuple, but since we aren't
1077-
* doing much work per tuple, the extra lock traffic is probably better
1078-
* avoided.
1074+
* under us. It comes from the stream already pinned. We also choose to
1075+
* hold sharelock on the buffer throughout --- we could release and
1076+
* re-acquire sharelock for each tuple, but since we aren't doing much
1077+
* work per tuple, the extra lock traffic is probably better avoided.
10791078
*/
1080-
hscan->rs_cblock = blockno;
1081-
hscan->rs_cindex = FirstOffsetNumber;
1082-
hscan->rs_cbuf = ReadBufferExtended(scan->rs_rd, MAIN_FORKNUM,
1083-
blockno, RBM_NORMAL, bstrategy);
1079+
hscan->rs_cbuf = read_stream_next_buffer(stream, NULL);
1080+
if (!BufferIsValid(hscan->rs_cbuf))
1081+
return false;
1082+
10841083
LockBuffer(hscan->rs_cbuf, BUFFER_LOCK_SHARE);
1084+
1085+
hscan->rs_cblock = BufferGetBlockNumber(hscan->rs_cbuf);
1086+
hscan->rs_cindex = FirstOffsetNumber;
1087+
return true;
10851088
}
10861089

10871090
/*

src/backend/commands/analyze.c

+25-60
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,20 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
11021102
return stats;
11031103
}
11041104

1105+
/*
1106+
* Read stream callback returning the next BlockNumber as chosen by the
1107+
* BlockSampling algorithm.
1108+
*/
1109+
static BlockNumber
1110+
block_sampling_read_stream_next(ReadStream *stream,
1111+
void *callback_private_data,
1112+
void *per_buffer_data)
1113+
{
1114+
BlockSamplerData *bs = callback_private_data;
1115+
1116+
return BlockSampler_HasMore(bs) ? BlockSampler_Next(bs) : InvalidBlockNumber;
1117+
}
1118+
11051119
/*
11061120
* acquire_sample_rows -- acquire a random sample of rows from the heap
11071121
*
@@ -1154,10 +1168,7 @@ acquire_sample_rows(Relation onerel, int elevel,
11541168
TableScanDesc scan;
11551169
BlockNumber nblocks;
11561170
BlockNumber blksdone = 0;
1157-
#ifdef USE_PREFETCH
1158-
int prefetch_maximum = 0; /* blocks to prefetch if enabled */
1159-
BlockSamplerData prefetch_bs;
1160-
#endif
1171+
ReadStream *stream;
11611172

11621173
Assert(targrows > 0);
11631174

@@ -1170,13 +1181,6 @@ acquire_sample_rows(Relation onerel, int elevel,
11701181
randseed = pg_prng_uint32(&pg_global_prng_state);
11711182
nblocks = BlockSampler_Init(&bs, totalblocks, targrows, randseed);
11721183

1173-
#ifdef USE_PREFETCH
1174-
prefetch_maximum = get_tablespace_maintenance_io_concurrency(onerel->rd_rel->reltablespace);
1175-
/* Create another BlockSampler, using the same seed, for prefetching */
1176-
if (prefetch_maximum)
1177-
(void) BlockSampler_Init(&prefetch_bs, totalblocks, targrows, randseed);
1178-
#endif
1179-
11801184
/* Report sampling block numbers */
11811185
pgstat_progress_update_param(PROGRESS_ANALYZE_BLOCKS_TOTAL,
11821186
nblocks);
@@ -1187,60 +1191,19 @@ acquire_sample_rows(Relation onerel, int elevel,
11871191
scan = heap_beginscan(onerel, NULL, 0, NULL, NULL, SO_TYPE_ANALYZE);
11881192
slot = table_slot_create(onerel, NULL);
11891193

1190-
#ifdef USE_PREFETCH
1191-
1192-
/*
1193-
* If we are doing prefetching, then go ahead and tell the kernel about
1194-
* the first set of pages we are going to want. This also moves our
1195-
* iterator out ahead of the main one being used, where we will keep it so
1196-
* that we're always pre-fetching out prefetch_maximum number of blocks
1197-
* ahead.
1198-
*/
1199-
if (prefetch_maximum)
1200-
{
1201-
for (int i = 0; i < prefetch_maximum; i++)
1202-
{
1203-
BlockNumber prefetch_block;
1204-
1205-
if (!BlockSampler_HasMore(&prefetch_bs))
1206-
break;
1207-
1208-
prefetch_block = BlockSampler_Next(&prefetch_bs);
1209-
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, prefetch_block);
1210-
}
1211-
}
1212-
#endif
1194+
stream = read_stream_begin_relation(READ_STREAM_MAINTENANCE,
1195+
vac_strategy,
1196+
scan->rs_rd,
1197+
MAIN_FORKNUM,
1198+
block_sampling_read_stream_next,
1199+
&bs,
1200+
0);
12131201

12141202
/* Outer loop over blocks to sample */
1215-
while (BlockSampler_HasMore(&bs))
1203+
while (heapam_scan_analyze_next_block(scan, stream))
12161204
{
1217-
BlockNumber targblock = BlockSampler_Next(&bs);
1218-
#ifdef USE_PREFETCH
1219-
BlockNumber prefetch_targblock = InvalidBlockNumber;
1220-
1221-
/*
1222-
* Make sure that every time the main BlockSampler is moved forward
1223-
* that our prefetch BlockSampler also gets moved forward, so that we
1224-
* always stay out ahead.
1225-
*/
1226-
if (prefetch_maximum && BlockSampler_HasMore(&prefetch_bs))
1227-
prefetch_targblock = BlockSampler_Next(&prefetch_bs);
1228-
#endif
1229-
12301205
vacuum_delay_point();
12311206

1232-
heapam_scan_analyze_next_block(scan, targblock, vac_strategy);
1233-
1234-
#ifdef USE_PREFETCH
1235-
1236-
/*
1237-
* When pre-fetching, after we get a block, tell the kernel about the
1238-
* next one we will want, if there's any left.
1239-
*/
1240-
if (prefetch_maximum && prefetch_targblock != InvalidBlockNumber)
1241-
PrefetchBuffer(scan->rs_rd, MAIN_FORKNUM, prefetch_targblock);
1242-
#endif
1243-
12441207
while (heapam_scan_analyze_next_tuple(scan, OldestXmin, &liverows, &deadrows, slot))
12451208
{
12461209
/*
@@ -1290,6 +1253,8 @@ acquire_sample_rows(Relation onerel, int elevel,
12901253
++blksdone);
12911254
}
12921255

1256+
read_stream_end(stream);
1257+
12931258
ExecDropSingleTupleTableSlot(slot);
12941259
heap_endscan(scan);
12951260

src/include/access/heapam.h

+2-3
Original file line numberDiff line numberDiff line change
@@ -413,9 +413,8 @@ extern bool HeapTupleIsSurelyDead(HeapTuple htup,
413413
struct GlobalVisState *vistest);
414414

415415
/* in heap/heapam_handler.c*/
416-
extern void heapam_scan_analyze_next_block(TableScanDesc scan,
417-
BlockNumber blockno,
418-
BufferAccessStrategy bstrategy);
416+
extern bool heapam_scan_analyze_next_block(TableScanDesc scan,
417+
ReadStream *stream);
419418
extern bool heapam_scan_analyze_next_tuple(TableScanDesc scan,
420419
TransactionId OldestXmin,
421420
double *liverows, double *deadrows,

0 commit comments

Comments
 (0)