@@ -67,7 +67,7 @@ static BrinBuildState *initialize_brin_buildstate(Relation idxRel,
67
67
BrinRevmap * revmap , BlockNumber pagesPerRange );
68
68
static void terminate_brin_buildstate (BrinBuildState * state );
69
69
static void brinsummarize (Relation index , Relation heapRel , BlockNumber pageRange ,
70
- double * numSummarized , double * numExisting );
70
+ bool include_partial , double * numSummarized , double * numExisting );
71
71
static void form_and_insert_tuple (BrinBuildState * state );
72
72
static void union_tuples (BrinDesc * bdesc , BrinMemTuple * a ,
73
73
BrinTuple * b );
@@ -789,7 +789,7 @@ brinvacuumcleanup(IndexVacuumInfo *info, IndexBulkDeleteResult *stats)
789
789
790
790
brin_vacuum_scan (info -> index , info -> strategy );
791
791
792
- brinsummarize (info -> index , heapRel , BRIN_ALL_BLOCKRANGES ,
792
+ brinsummarize (info -> index , heapRel , BRIN_ALL_BLOCKRANGES , false,
793
793
& stats -> num_index_tuples , & stats -> num_index_tuples );
794
794
795
795
heap_close (heapRel , AccessShareLock );
@@ -907,7 +907,7 @@ brin_summarize_range(PG_FUNCTION_ARGS)
907
907
RelationGetRelationName (indexRel ))));
908
908
909
909
/* OK, do it */
910
- brinsummarize (indexRel , heapRel , heapBlk , & numSummarized , NULL );
910
+ brinsummarize (indexRel , heapRel , heapBlk , true, & numSummarized , NULL );
911
911
912
912
relation_close (indexRel , ShareUpdateExclusiveLock );
913
913
relation_close (heapRel , ShareUpdateExclusiveLock );
@@ -1127,7 +1127,8 @@ terminate_brin_buildstate(BrinBuildState *state)
1127
1127
}
1128
1128
1129
1129
/*
1130
- * Summarize the given page range of the given index.
1130
+ * On the given BRIN index, summarize the heap page range that corresponds
1131
+ * to the heap block number given.
1131
1132
*
1132
1133
* This routine can run in parallel with insertions into the heap. To avoid
1133
1134
* missing those values from the summary tuple, we first insert a placeholder
@@ -1137,6 +1138,12 @@ terminate_brin_buildstate(BrinBuildState *state)
1137
1138
* update of the index value happens in a loop, so that if somebody updates
1138
1139
* the placeholder tuple after we read it, we detect the case and try again.
1139
1140
* This ensures that the concurrently inserted tuples are not lost.
1141
+ *
1142
+ * A further corner case is this routine being asked to summarize the partial
1143
+ * range at the end of the table. heapNumBlocks is the (possibly outdated)
1144
+ * table size; if we notice that the requested range lies beyond that size,
1145
+ * we re-compute the table size after inserting the placeholder tuple, to
1146
+ * avoid missing pages that were appended recently.
1140
1147
*/
1141
1148
static void
1142
1149
summarize_range (IndexInfo * indexInfo , BrinBuildState * state , Relation heapRel ,
@@ -1157,6 +1164,33 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel,
1157
1164
state -> bs_rmAccess , & phbuf ,
1158
1165
heapBlk , phtup , phsz );
1159
1166
1167
+ /*
1168
+ * Compute range end. We hold ShareUpdateExclusive lock on table, so it
1169
+ * cannot shrink concurrently (but it can grow).
1170
+ */
1171
+ Assert (heapBlk % state -> bs_pagesPerRange == 0 );
1172
+ if (heapBlk + state -> bs_pagesPerRange > heapNumBlks )
1173
+ {
1174
+ /*
1175
+ * If we're asked to scan what we believe to be the final range on the
1176
+ * table (i.e. a range that might be partial) we need to recompute our
1177
+ * idea of what the latest page is after inserting the placeholder
1178
+ * tuple. Anyone that grows the table later will update the
1179
+ * placeholder tuple, so it doesn't matter that we won't scan these
1180
+ * pages ourselves. Careful: the table might have been extended
1181
+ * beyond the current range, so clamp our result.
1182
+ *
1183
+ * Fortunately, this should occur infrequently.
1184
+ */
1185
+ scanNumBlks = Min (RelationGetNumberOfBlocks (heapRel ) - heapBlk ,
1186
+ state -> bs_pagesPerRange );
1187
+ }
1188
+ else
1189
+ {
1190
+ /* Easy case: range is known to be complete */
1191
+ scanNumBlks = state -> bs_pagesPerRange ;
1192
+ }
1193
+
1160
1194
/*
1161
1195
* Execute the partial heap scan covering the heap blocks in the specified
1162
1196
* page range, summarizing the heap tuples in it. This scan stops just
@@ -1167,8 +1201,6 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel,
1167
1201
* by transactions that are still in progress, among other corner cases.
1168
1202
*/
1169
1203
state -> bs_currRangeStart = heapBlk ;
1170
- scanNumBlks = heapBlk + state -> bs_pagesPerRange <= heapNumBlks ?
1171
- state -> bs_pagesPerRange : heapNumBlks - heapBlk ;
1172
1204
IndexBuildHeapRangeScan (heapRel , state -> bs_irel , indexInfo , false, true,
1173
1205
heapBlk , scanNumBlks ,
1174
1206
brinbuildCallback , (void * ) state );
@@ -1232,63 +1264,63 @@ summarize_range(IndexInfo *indexInfo, BrinBuildState *state, Relation heapRel,
1232
1264
* Summarize page ranges that are not already summarized. If pageRange is
1233
1265
* BRIN_ALL_BLOCKRANGES then the whole table is scanned; otherwise, only the
1234
1266
* page range containing the given heap page number is scanned.
1267
+ * If include_partial is true, then the partial range at the end of the table
1268
+ * is summarized, otherwise not.
1235
1269
*
1236
1270
* For each new index tuple inserted, *numSummarized (if not NULL) is
1237
1271
* incremented; for each existing tuple, *numExisting (if not NULL) is
1238
1272
* incremented.
1239
1273
*/
1240
1274
static void
1241
1275
brinsummarize (Relation index , Relation heapRel , BlockNumber pageRange ,
1242
- double * numSummarized , double * numExisting )
1276
+ bool include_partial , double * numSummarized , double * numExisting )
1243
1277
{
1244
1278
BrinRevmap * revmap ;
1245
1279
BrinBuildState * state = NULL ;
1246
1280
IndexInfo * indexInfo = NULL ;
1247
1281
BlockNumber heapNumBlocks ;
1248
- BlockNumber heapBlk ;
1249
1282
BlockNumber pagesPerRange ;
1250
1283
Buffer buf ;
1251
1284
BlockNumber startBlk ;
1252
- BlockNumber endBlk ;
1253
-
1254
- /* determine range of pages to process; nothing to do for an empty table */
1255
- heapNumBlocks = RelationGetNumberOfBlocks (heapRel );
1256
- if (heapNumBlocks == 0 )
1257
- return ;
1258
1285
1259
1286
revmap = brinRevmapInitialize (index , & pagesPerRange , NULL );
1260
1287
1288
+ /* determine range of pages to process */
1289
+ heapNumBlocks = RelationGetNumberOfBlocks (heapRel );
1261
1290
if (pageRange == BRIN_ALL_BLOCKRANGES )
1262
- {
1263
1291
startBlk = 0 ;
1264
- endBlk = heapNumBlocks ;
1265
- }
1266
1292
else
1267
- {
1268
1293
startBlk = (pageRange / pagesPerRange ) * pagesPerRange ;
1294
+ if (startBlk >= heapNumBlocks )
1295
+ {
1269
1296
/* Nothing to do if start point is beyond end of table */
1270
- if (startBlk > heapNumBlocks )
1271
- {
1272
- brinRevmapTerminate (revmap );
1273
- return ;
1274
- }
1275
- endBlk = startBlk + pagesPerRange ;
1276
- if (endBlk > heapNumBlocks )
1277
- endBlk = heapNumBlocks ;
1297
+ brinRevmapTerminate (revmap );
1298
+ return ;
1278
1299
}
1279
1300
1280
1301
/*
1281
1302
* Scan the revmap to find unsummarized items.
1282
1303
*/
1283
1304
buf = InvalidBuffer ;
1284
- for (heapBlk = startBlk ; heapBlk < endBlk ; heapBlk += pagesPerRange )
1305
+ for (; startBlk < heapNumBlocks ; startBlk += pagesPerRange )
1285
1306
{
1286
1307
BrinTuple * tup ;
1287
1308
OffsetNumber off ;
1288
1309
1310
+ /*
1311
+ * Unless requested to summarize even a partial range, go away now if
1312
+ * we think the next range is partial. Caller would pass true when
1313
+ * it is typically run once bulk data loading is done
1314
+ * (brin_summarize_new_values), and false when it is typically the
1315
+ * result of arbitrarily-scheduled maintenance command (vacuuming).
1316
+ */
1317
+ if (!include_partial &&
1318
+ (startBlk + pagesPerRange > heapNumBlocks ))
1319
+ break ;
1320
+
1289
1321
CHECK_FOR_INTERRUPTS ();
1290
1322
1291
- tup = brinGetTupleForHeapBlock (revmap , heapBlk , & buf , & off , NULL ,
1323
+ tup = brinGetTupleForHeapBlock (revmap , startBlk , & buf , & off , NULL ,
1292
1324
BUFFER_LOCK_SHARE , NULL );
1293
1325
if (tup == NULL )
1294
1326
{
@@ -1301,7 +1333,7 @@ brinsummarize(Relation index, Relation heapRel, BlockNumber pageRange,
1301
1333
pagesPerRange );
1302
1334
indexInfo = BuildIndexInfo (index );
1303
1335
}
1304
- summarize_range (indexInfo , state , heapRel , heapBlk , heapNumBlocks );
1336
+ summarize_range (indexInfo , state , heapRel , startBlk , heapNumBlocks );
1305
1337
1306
1338
/* and re-initialize state for the next range */
1307
1339
brin_memtuple_initialize (state -> bs_dtuple , state -> bs_bdesc );
0 commit comments