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

Commit cb44a83

Browse files
committed
Fix parallel BRIN builds with synchronized scans
The brinbuildCallbackParallel callback used by parallel BRIN builds did not consider that the parallel table scans may be synchronized, starting from an arbitrary block and then wrap around. If this happened and the scan actually did wrap around, tuples from the beginning of the table were added to the last range produced by the same worker. The index would be missing range at the beginning of the table, while the last range would be too wide. This would not produce incorrect query results, but it'd be less efficient. Fixed by checking for both past and future ranges in the callback. The worker may produce multiple summaries for the same page range, but the leader will merge them as if the summaries came from different workers. Discussion: https://postgr.es/m/c2ee7d69-ce17-43f2-d1a0-9811edbda6e6%40enterprisedb.com
1 parent 6c63bcb commit cb44a83

File tree

1 file changed

+12
-4
lines changed

1 file changed

+12
-4
lines changed

src/backend/access/brin/brin.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,16 +1040,22 @@ brinbuildCallbackParallel(Relation index,
10401040
thisblock = ItemPointerGetBlockNumber(tid);
10411041

10421042
/*
1043-
* If we're in a block that belongs to a future range, summarize what
1043+
* If we're in a block that belongs to a different range, summarize what
10441044
* we've got and start afresh. Note the scan might have skipped many
10451045
* pages, if they were devoid of live tuples; we do not create emptry BRIN
10461046
* ranges here - the leader is responsible for filling them in.
1047+
*
1048+
* Unlike serial builds, parallel index builds allow synchronized seqscans
1049+
* (because that's what parallel scans do). This means the block may wrap
1050+
* around to the beginning of the relation, so the condition needs to
1051+
* check for both future and past ranges.
10471052
*/
1048-
if (thisblock > state->bs_currRangeStart + state->bs_pagesPerRange - 1)
1053+
if ((thisblock < state->bs_currRangeStart) ||
1054+
(thisblock > state->bs_currRangeStart + state->bs_pagesPerRange - 1))
10491055
{
10501056

10511057
BRIN_elog((DEBUG2,
1052-
"brinbuildCallback: completed a range: %u--%u",
1058+
"brinbuildCallbackParallel: completed a range: %u--%u",
10531059
state->bs_currRangeStart,
10541060
state->bs_currRangeStart + state->bs_pagesPerRange));
10551061

@@ -1201,7 +1207,9 @@ brinbuild(Relation heap, Relation index, IndexInfo *indexInfo)
12011207
{
12021208
/*
12031209
* Now scan the relation. No syncscan allowed here because we want
1204-
* the heap blocks in physical order.
1210+
* the heap blocks in physical order (we want to produce the ranges
1211+
* starting from block 0, and the callback also relies on this to not
1212+
* generate summary for the same range twice).
12051213
*/
12061214
reltuples = table_index_build_scan(heap, index, indexInfo, false, true,
12071215
brinbuildCallback, (void *) state, NULL);

0 commit comments

Comments
 (0)