=== Applying patches on top of PostgreSQL commit ID 98b1efd6ef6a1612019ef9ed6e44b79c132352ce === /etc/rc.d/jail: WARNING: Per-jail configuration via jail_* variables is obsolete. Please consider migrating to /etc/jail.conf. Tue Dec 31 06:48:24 UTC 2024 On branch cf/5026 nothing to commit, working tree clean === applying patch ./v20241008-0001-WIP-parallel-GiST-build.patch Applied patch to 'src/backend/access/gist/gist.c' cleanly. Applied patch to 'src/backend/access/gist/gistbuild.c' with conflicts. Applied patch to 'src/backend/access/gist/gistutil.c' cleanly. Applied patch to 'src/backend/access/gist/gistvacuum.c' cleanly. Applied patch to 'src/backend/access/transam/parallel.c' cleanly. Applied patch to 'src/include/access/gist_private.h' cleanly. Applied patch to 'src/tools/pgindent/typedefs.list' cleanly. U src/backend/access/gist/gistbuild.c diff --cc src/backend/access/gist/gistbuild.c index 3a2759b446,e647b1e66c..0000000000 --- a/src/backend/access/gist/gistbuild.c +++ b/src/backend/access/gist/gistbuild.c @@@ -309,37 -452,79 +452,87 @@@ gistbuild(Relation heap, Relation index END_CRIT_SECTION(); ++<<<<<<< ours + /* Scan the table, inserting all the tuples to the index. */ + reltuples = table_index_build_scan(heap, index, indexInfo, true, true, + gistBuildCallback, + &buildstate, NULL); + ++======= ++>>>>>>> theirs /* - * If buffering was used, flush out all the tuples that are still in - * the buffers. + * Attempt to launch parallel worker scan when required + * + * XXX plan_create_index_workers makes the number of workers dependent + * on maintenance_work_mem, requiring 32MB for each worker. That makes + * sense for btree, but maybe not for GIST (at least when not using + * buffering)? So maybe make that somehow less strict, optionally? */ - if (buildstate.buildMode == GIST_BUFFERING_ACTIVE) - { - elog(DEBUG1, "all tuples processed, emptying buffers"); - gistEmptyAllBuffers(&buildstate); - gistFreeBuildBuffers(buildstate.gfbb); - } + if (indexInfo->ii_ParallelWorkers > 0) + _gist_begin_parallel(&buildstate, heap, + index, indexInfo->ii_Concurrent, + indexInfo->ii_ParallelWorkers); /* - * We didn't write WAL records as we built the index, so if - * WAL-logging is required, write all pages to the WAL now. + * If parallel build requested and at least one worker process was + * successfully launched, set up coordination state, wait for workers + * to complete and end the parallel build. + * + * In serial mode, simply scan the table and build the index one index + * tuple at a time. */ - if (RelationNeedsWAL(index)) + if (buildstate.gist_leader) { - log_newpage_range(index, MAIN_FORKNUM, - 0, RelationGetNumberOfBlocks(index), - true); + /* scan the relation and wait for parallel workers to finish */ + reltuples = _gist_parallel_heapscan(&buildstate); + + _gist_end_parallel(buildstate.gist_leader, &buildstate); + + /* + * We didn't write WAL records as we built the index, so if WAL-logging is + * required, write all pages to the WAL now. + */ + if (RelationNeedsWAL(index)) + { + log_newpage_range(index, MAIN_FORKNUM, + 0, RelationGetNumberOfBlocks(index), + true); + } } - } + else + { + /* Scan the table, inserting all the tuples to the index. */ + reltuples = table_index_build_scan(heap, index, indexInfo, true, true, + gistBuildCallback, + (void *) &buildstate, NULL); - /* okay, all heap tuples are indexed */ - MemoryContextSwitchTo(oldcxt); - MemoryContextDelete(buildstate.giststate->tempCxt); + /* + * If buffering was used, flush out all the tuples that are still + * in the buffers. + */ + if (buildstate.buildMode == GIST_BUFFERING_ACTIVE) + { + elog(DEBUG1, "all tuples processed, emptying buffers"); + gistEmptyAllBuffers(&buildstate); + gistFreeBuildBuffers(buildstate.gfbb); + } + + /* + * We didn't write WAL records as we built the index, so if + * WAL-logging is required, write all pages to the WAL now. + */ + if (RelationNeedsWAL(index)) + { + log_newpage_range(index, MAIN_FORKNUM, + 0, RelationGetNumberOfBlocks(index), + true); + } + + /* okay, all heap tuples are indexed */ + MemoryContextSwitchTo(oldcxt); + MemoryContextDelete(buildstate.giststate->tempCxt); + } + } freeGISTstate(buildstate.giststate);