1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-11 20:28:21 +03:00

pg_stat_statements: Add columns to track parallel worker activity

The view pg_stat_statements gains two columns:
- parallel_workers_to_launch, the number of parallel workers planned to
be launched.
- parallel_workers_launched, the number of parallel workers actually
launched.

The ratio of both columns offers hints that parallel workers are lacking
on a per-statement basis, requiring some tuning, in coordination with
"calls", the number of times a query is executed.

As of now, these numbers are tracked within Gather and GatherMerge
nodes.  They could be extended to utilities that make use of parallel
workers (parallel btree and brin, VACUUM).

The module is bumped to 1.12.

Author: Guillaume Lelarge
Discussion: https://postgr.es/m/CAECtzeWtTGOK0UgKXdDGpfTVSa5bd_VbUt6K6xn8P7X+_dZqKw@mail.gmail.com
This commit is contained in:
Michael Paquier
2024-10-09 08:30:45 +09:00
parent de3a2ea3b2
commit cf54a2c002
10 changed files with 281 additions and 11 deletions

View File

@ -113,6 +113,7 @@ typedef enum pgssVersion
PGSS_V1_9,
PGSS_V1_10,
PGSS_V1_11,
PGSS_V1_12,
} pgssVersion;
typedef enum pgssStoreKind
@ -204,6 +205,10 @@ typedef struct Counters
int64 jit_emission_count; /* number of times emission time has been
* > 0 */
double jit_emission_time; /* total time to emit jit code */
int64 parallel_workers_to_launch; /* # of parallel workers planned
* to be launched */
int64 parallel_workers_launched; /* # of parallel workers actually
* launched */
} Counters;
/*
@ -317,6 +322,7 @@ PG_FUNCTION_INFO_V1(pg_stat_statements_1_8);
PG_FUNCTION_INFO_V1(pg_stat_statements_1_9);
PG_FUNCTION_INFO_V1(pg_stat_statements_1_10);
PG_FUNCTION_INFO_V1(pg_stat_statements_1_11);
PG_FUNCTION_INFO_V1(pg_stat_statements_1_12);
PG_FUNCTION_INFO_V1(pg_stat_statements);
PG_FUNCTION_INFO_V1(pg_stat_statements_info);
@ -347,7 +353,9 @@ static void pgss_store(const char *query, uint64 queryId,
const BufferUsage *bufusage,
const WalUsage *walusage,
const struct JitInstrumentation *jitusage,
JumbleState *jstate);
JumbleState *jstate,
int parallel_workers_to_launch,
int parallel_workers_launched);
static void pg_stat_statements_internal(FunctionCallInfo fcinfo,
pgssVersion api_version,
bool showtext);
@ -867,7 +875,9 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
NULL,
NULL,
NULL,
jstate);
jstate,
0,
0);
}
/*
@ -945,7 +955,9 @@ pgss_planner(Query *parse,
&bufusage,
&walusage,
NULL,
NULL);
NULL,
0,
0);
}
else
{
@ -1078,7 +1090,9 @@ pgss_ExecutorEnd(QueryDesc *queryDesc)
&queryDesc->totaltime->bufusage,
&queryDesc->totaltime->walusage,
queryDesc->estate->es_jit ? &queryDesc->estate->es_jit->instr : NULL,
NULL);
NULL,
queryDesc->estate->es_parallel_workers_to_launch,
queryDesc->estate->es_parallel_workers_launched);
}
if (prev_ExecutorEnd)
@ -1209,7 +1223,9 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
&bufusage,
&walusage,
NULL,
NULL);
NULL,
0,
0);
}
else
{
@ -1270,7 +1286,9 @@ pgss_store(const char *query, uint64 queryId,
const BufferUsage *bufusage,
const WalUsage *walusage,
const struct JitInstrumentation *jitusage,
JumbleState *jstate)
JumbleState *jstate,
int parallel_workers_to_launch,
int parallel_workers_launched)
{
pgssHashKey key;
pgssEntry *entry;
@ -1473,6 +1491,10 @@ pgss_store(const char *query, uint64 queryId,
entry->counters.jit_emission_time += INSTR_TIME_GET_MILLISEC(jitusage->emission_counter);
}
/* parallel worker counters */
entry->counters.parallel_workers_to_launch += parallel_workers_to_launch;
entry->counters.parallel_workers_launched += parallel_workers_launched;
SpinLockRelease(&entry->mutex);
}
@ -1539,7 +1561,8 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
#define PG_STAT_STATEMENTS_COLS_V1_9 33
#define PG_STAT_STATEMENTS_COLS_V1_10 43
#define PG_STAT_STATEMENTS_COLS_V1_11 49
#define PG_STAT_STATEMENTS_COLS 49 /* maximum of above */
#define PG_STAT_STATEMENTS_COLS_V1_12 51
#define PG_STAT_STATEMENTS_COLS 51 /* maximum of above */
/*
* Retrieve statement statistics.
@ -1551,6 +1574,16 @@ pg_stat_statements_reset(PG_FUNCTION_ARGS)
* expected API version is identified by embedding it in the C name of the
* function. Unfortunately we weren't bright enough to do that for 1.1.
*/
Datum
pg_stat_statements_1_12(PG_FUNCTION_ARGS)
{
bool showtext = PG_GETARG_BOOL(0);
pg_stat_statements_internal(fcinfo, PGSS_V1_12, showtext);
return (Datum) 0;
}
Datum
pg_stat_statements_1_11(PG_FUNCTION_ARGS)
{
@ -1695,6 +1728,10 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
if (api_version != PGSS_V1_11)
elog(ERROR, "incorrect number of output arguments");
break;
case PG_STAT_STATEMENTS_COLS_V1_12:
if (api_version != PGSS_V1_12)
elog(ERROR, "incorrect number of output arguments");
break;
default:
elog(ERROR, "incorrect number of output arguments");
}
@ -1932,6 +1969,14 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
{
values[i++] = Int64GetDatumFast(tmp.jit_deform_count);
values[i++] = Float8GetDatumFast(tmp.jit_deform_time);
}
if (api_version >= PGSS_V1_12)
{
values[i++] = Int64GetDatumFast(tmp.parallel_workers_to_launch);
values[i++] = Int64GetDatumFast(tmp.parallel_workers_launched);
}
if (api_version >= PGSS_V1_11)
{
values[i++] = TimestampTzGetDatum(stats_since);
values[i++] = TimestampTzGetDatum(minmax_stats_since);
}
@ -1944,6 +1989,7 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
api_version == PGSS_V1_9 ? PG_STAT_STATEMENTS_COLS_V1_9 :
api_version == PGSS_V1_10 ? PG_STAT_STATEMENTS_COLS_V1_10 :
api_version == PGSS_V1_11 ? PG_STAT_STATEMENTS_COLS_V1_11 :
api_version == PGSS_V1_12 ? PG_STAT_STATEMENTS_COLS_V1_12 :
-1 /* fail if you forget to update this assert */ ));
tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);