Allow parallel create index to accumulate buffer usage stats.
Currently, we don't account for buffer usage incurred by parallel workers for parallel create index. This commit allows each worker to record the buffer usage stats and leader backend to accumulate that stats at the end of the operation. This will allow pg_stat_statements to display correct buffer usage stats for (parallel) create index command. Reported-by: Julien Rouhaud Author: Sawada Masahiko Reviewed-by: Dilip Kumar, Julien Rouhaud and Amit Kapila Backpatch-through: 11, where this was introduced Discussion: https://postgr.es/m/20200328151721.GB12854@nol
This commit is contained in:
parent
d050c61137
commit
f179e9f01b
@ -64,6 +64,7 @@
|
||||
#include "access/xlog.h"
|
||||
#include "access/xloginsert.h"
|
||||
#include "catalog/index.h"
|
||||
#include "executor/instrument.h"
|
||||
#include "miscadmin.h"
|
||||
#include "pgstat.h"
|
||||
#include "storage/smgr.h"
|
||||
@ -78,6 +79,7 @@
|
||||
#define PARALLEL_KEY_TUPLESORT UINT64CONST(0xA000000000000002)
|
||||
#define PARALLEL_KEY_TUPLESORT_SPOOL2 UINT64CONST(0xA000000000000003)
|
||||
#define PARALLEL_KEY_QUERY_TEXT UINT64CONST(0xA000000000000004)
|
||||
#define PARALLEL_KEY_BUFFER_USAGE UINT64CONST(0xA000000000000005)
|
||||
|
||||
/*
|
||||
* DISABLE_LEADER_PARTICIPATION disables the leader's participation in
|
||||
@ -192,6 +194,7 @@ typedef struct BTLeader
|
||||
Sharedsort *sharedsort;
|
||||
Sharedsort *sharedsort2;
|
||||
Snapshot snapshot;
|
||||
BufferUsage *bufferusage;
|
||||
} BTLeader;
|
||||
|
||||
/*
|
||||
@ -1240,6 +1243,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
|
||||
Sharedsort *sharedsort2;
|
||||
BTSpool *btspool = buildstate->spool;
|
||||
BTLeader *btleader = (BTLeader *) palloc0(sizeof(BTLeader));
|
||||
BufferUsage *bufferusage;
|
||||
bool leaderparticipates = true;
|
||||
char *sharedquery;
|
||||
int querylen;
|
||||
@ -1292,6 +1296,17 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
|
||||
shm_toc_estimate_keys(&pcxt->estimator, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimate space for BufferUsage -- PARALLEL_KEY_BUFFER_USAGE.
|
||||
*
|
||||
* If there are no extensions loaded that care, we could skip this. We
|
||||
* have no way of knowing whether anyone's looking at pgBufferUsage, so do
|
||||
* it unconditionally.
|
||||
*/
|
||||
shm_toc_estimate_chunk(&pcxt->estimator,
|
||||
mul_size(sizeof(BufferUsage), pcxt->nworkers));
|
||||
shm_toc_estimate_keys(&pcxt->estimator, 1);
|
||||
|
||||
/* Finally, estimate PARALLEL_KEY_QUERY_TEXT space */
|
||||
querylen = strlen(debug_query_string);
|
||||
shm_toc_estimate_chunk(&pcxt->estimator, querylen + 1);
|
||||
@ -1361,6 +1376,11 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
|
||||
memcpy(sharedquery, debug_query_string, querylen + 1);
|
||||
shm_toc_insert(pcxt->toc, PARALLEL_KEY_QUERY_TEXT, sharedquery);
|
||||
|
||||
/* Allocate space for each worker's BufferUsage; no need to initialize */
|
||||
bufferusage = shm_toc_allocate(pcxt->toc,
|
||||
mul_size(sizeof(BufferUsage), pcxt->nworkers));
|
||||
shm_toc_insert(pcxt->toc, PARALLEL_KEY_BUFFER_USAGE, bufferusage);
|
||||
|
||||
/* Launch workers, saving status for leader/caller */
|
||||
LaunchParallelWorkers(pcxt);
|
||||
btleader->pcxt = pcxt;
|
||||
@ -1371,6 +1391,7 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
|
||||
btleader->sharedsort = sharedsort;
|
||||
btleader->sharedsort2 = sharedsort2;
|
||||
btleader->snapshot = snapshot;
|
||||
btleader->bufferusage = bufferusage;
|
||||
|
||||
/* If no workers were successfully launched, back out (do serial build) */
|
||||
if (pcxt->nworkers_launched == 0)
|
||||
@ -1399,8 +1420,18 @@ _bt_begin_parallel(BTBuildState *buildstate, bool isconcurrent, int request)
|
||||
static void
|
||||
_bt_end_parallel(BTLeader *btleader)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Shutdown worker processes */
|
||||
WaitForParallelWorkersToFinish(btleader->pcxt);
|
||||
|
||||
/*
|
||||
* Next, accumulate buffer usage. (This must wait for the workers to
|
||||
* finish, or we might get incomplete data.)
|
||||
*/
|
||||
for (i = 0; i < btleader->pcxt->nworkers_launched; i++)
|
||||
InstrAccumParallelQuery(&btleader->bufferusage[i]);
|
||||
|
||||
/* Free last reference to MVCC snapshot, if one was used */
|
||||
if (IsMVCCSnapshot(btleader->snapshot))
|
||||
UnregisterSnapshot(btleader->snapshot);
|
||||
@ -1537,6 +1568,7 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
|
||||
Relation indexRel;
|
||||
LOCKMODE heapLockmode;
|
||||
LOCKMODE indexLockmode;
|
||||
BufferUsage *bufferusage;
|
||||
int sortmem;
|
||||
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
@ -1598,11 +1630,18 @@ _bt_parallel_build_main(dsm_segment *seg, shm_toc *toc)
|
||||
tuplesort_attach_shared(sharedsort2, seg);
|
||||
}
|
||||
|
||||
/* Prepare to track buffer usage during parallel execution */
|
||||
InstrStartParallelQuery();
|
||||
|
||||
/* Perform sorting of spool, and possibly a spool2 */
|
||||
sortmem = maintenance_work_mem / btshared->scantuplesortstates;
|
||||
_bt_parallel_scan_and_sort(btspool, btspool2, btshared, sharedsort,
|
||||
sharedsort2, sortmem);
|
||||
|
||||
/* Report buffer usage during parallel execution */
|
||||
bufferusage = shm_toc_lookup(toc, PARALLEL_KEY_BUFFER_USAGE, false);
|
||||
InstrEndParallelQuery(&bufferusage[ParallelWorkerNumber]);
|
||||
|
||||
#ifdef BTREE_BUILD_STATS
|
||||
if (log_btree_build_stats)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user