@ -1102,6 +1102,20 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
return stats ;
}
/*
* Read stream callback returning the next BlockNumber as chosen by the
* BlockSampling algorithm .
*/
static BlockNumber
block_sampling_read_stream_next ( ReadStream * stream ,
void * callback_private_data ,
void * per_buffer_data )
{
BlockSamplerData * bs = callback_private_data ;
return BlockSampler_HasMore ( bs ) ? BlockSampler_Next ( bs ) : InvalidBlockNumber ;
}
/*
* acquire_sample_rows - - acquire a random sample of rows from the heap
*
@ -1154,10 +1168,7 @@ acquire_sample_rows(Relation onerel, int elevel,
TableScanDesc scan ;
BlockNumber nblocks ;
BlockNumber blksdone = 0 ;
# ifdef USE_PREFETCH
int prefetch_maximum = 0 ; /* blocks to prefetch if enabled */
BlockSamplerData prefetch_bs ;
# endif
ReadStream * stream ;
Assert ( targrows > 0 ) ;
@ -1170,13 +1181,6 @@ acquire_sample_rows(Relation onerel, int elevel,
randseed = pg_prng_uint32 ( & pg_global_prng_state ) ;
nblocks = BlockSampler_Init ( & bs , totalblocks , targrows , randseed ) ;
# ifdef USE_PREFETCH
prefetch_maximum = get_tablespace_maintenance_io_concurrency ( onerel - > rd_rel - > reltablespace ) ;
/* Create another BlockSampler, using the same seed, for prefetching */
if ( prefetch_maximum )
( void ) BlockSampler_Init ( & prefetch_bs , totalblocks , targrows , randseed ) ;
# endif
/* Report sampling block numbers */
pgstat_progress_update_param ( PROGRESS_ANALYZE_BLOCKS_TOTAL ,
nblocks ) ;
@ -1187,60 +1191,19 @@ acquire_sample_rows(Relation onerel, int elevel,
scan = heap_beginscan ( onerel , NULL , 0 , NULL , NULL , SO_TYPE_ANALYZE ) ;
slot = table_slot_create ( onerel , NULL ) ;
# ifdef USE_PREFETCH
/*
* If we are doing prefetching , then go ahead and tell the kernel about
* the first set of pages we are going to want . This also moves our
* iterator out ahead of the main one being used , where we will keep it so
* that we ' re always pre - fetching out prefetch_maximum number of blocks
* ahead .
*/
if ( prefetch_maximum )
{
for ( int i = 0 ; i < prefetch_maximum ; i + + )
{
BlockNumber prefetch_block ;
if ( ! BlockSampler_HasMore ( & prefetch_bs ) )
break ;
prefetch_block = BlockSampler_Next ( & prefetch_bs ) ;
PrefetchBuffer ( scan - > rs_rd , MAIN_FORKNUM , prefetch_block ) ;
}
}
# endif
stream = read_stream_begin_relation ( READ_STREAM_MAINTENANCE ,
vac_strategy ,
scan - > rs_rd ,
MAIN_FORKNUM ,
block_sampling_read_stream_next ,
& bs ,
0 ) ;
/* Outer loop over blocks to sample */
while ( BlockSampler_HasMore ( & bs ) )
while ( heapam_scan_analyze_next_block ( scan , stream ) )
{
BlockNumber targblock = BlockSampler_Next ( & bs ) ;
# ifdef USE_PREFETCH
BlockNumber prefetch_targblock = InvalidBlockNumber ;
/*
* Make sure that every time the main BlockSampler is moved forward
* that our prefetch BlockSampler also gets moved forward , so that we
* always stay out ahead .
*/
if ( prefetch_maximum & & BlockSampler_HasMore ( & prefetch_bs ) )
prefetch_targblock = BlockSampler_Next ( & prefetch_bs ) ;
# endif
vacuum_delay_point ( ) ;
heapam_scan_analyze_next_block ( scan , targblock , vac_strategy ) ;
# ifdef USE_PREFETCH
/*
* When pre - fetching , after we get a block , tell the kernel about the
* next one we will want , if there ' s any left .
*/
if ( prefetch_maximum & & prefetch_targblock ! = InvalidBlockNumber )
PrefetchBuffer ( scan - > rs_rd , MAIN_FORKNUM , prefetch_targblock ) ;
# endif
while ( heapam_scan_analyze_next_tuple ( scan , OldestXmin , & liverows , & deadrows , slot ) )
{
/*
@ -1290,6 +1253,8 @@ acquire_sample_rows(Relation onerel, int elevel,
+ + blksdone ) ;
}
read_stream_end ( stream ) ;
ExecDropSingleTupleTableSlot ( slot ) ;
heap_endscan ( scan ) ;