Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 041b968

Browse filesBrowse 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
Copy full SHA for 041b968

File tree

Expand file treeCollapse file tree

3 files changed

+43
-76
lines changed
Filter options
Expand file treeCollapse file tree

3 files changed

+43
-76
lines changed

‎src/backend/access/heap/heapam_handler.c

Copy file name to clipboardExpand all lines: src/backend/access/heap/heapam_handler.c
+16-13Lines changed: 16 additions & 13 deletions
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

Copy file name to clipboardExpand all lines: src/backend/commands/analyze.c
+25-60Lines changed: 25 additions & 60 deletions
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

Copy file name to clipboardExpand all lines: src/include/access/heapam.h
+2-3Lines changed: 2 additions & 3 deletions
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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.