Make use of in-core query id added by commit 5fd9dfa5f5
Use the in-core query id computation for pg_stat_activity, log_line_prefix, and EXPLAIN VERBOSE. Similar to other fields in pg_stat_activity, only the queryid from the top level statements are exposed, and if the backends status isn't active then the queryid from the last executed statements is displayed. Add a %Q placeholder to include the queryid in log_line_prefix, which will also only expose top level statements. For EXPLAIN VERBOSE, if a query identifier has been computed, either by enabling compute_query_id or using a third-party module, display it. Bump catalog version. Discussion: https://postgr.es/m/20210407125726.tkvjdbw76hxnpwfi@nol Author: Julien Rouhaud Reviewed-by: Alvaro Herrera, Nitin Jadhav, Zhihong Yu
This commit is contained in:
parent
ec7ffb8096
commit
4f0b0966c8
@ -67,6 +67,7 @@
|
|||||||
#include "tcop/utility.h"
|
#include "tcop/utility.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
#include "utils/queryjumble.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/timestamp.h"
|
#include "utils/timestamp.h"
|
||||||
|
|
||||||
@ -101,6 +102,14 @@ static const uint32 PGSS_PG_MAJOR_VERSION = PG_VERSION_NUM / 100;
|
|||||||
#define USAGE_DEALLOC_PERCENT 5 /* free this % of entries at once */
|
#define USAGE_DEALLOC_PERCENT 5 /* free this % of entries at once */
|
||||||
#define IS_STICKY(c) ((c.calls[PGSS_PLAN] + c.calls[PGSS_EXEC]) == 0)
|
#define IS_STICKY(c) ((c.calls[PGSS_PLAN] + c.calls[PGSS_EXEC]) == 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility statements that pgss_ProcessUtility and pgss_post_parse_analyze
|
||||||
|
* ignores.
|
||||||
|
*/
|
||||||
|
#define PGSS_HANDLED_UTILITY(n) (!IsA(n, ExecuteStmt) && \
|
||||||
|
!IsA(n, PrepareStmt) && \
|
||||||
|
!IsA(n, DeallocateStmt))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extension version number, for supporting older extension versions' objects
|
* Extension version number, for supporting older extension versions' objects
|
||||||
*/
|
*/
|
||||||
@ -309,7 +318,6 @@ static void pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||||||
ProcessUtilityContext context, ParamListInfo params,
|
ProcessUtilityContext context, ParamListInfo params,
|
||||||
QueryEnvironment *queryEnv,
|
QueryEnvironment *queryEnv,
|
||||||
DestReceiver *dest, QueryCompletion *qc);
|
DestReceiver *dest, QueryCompletion *qc);
|
||||||
static uint64 pgss_hash_string(const char *str, int len);
|
|
||||||
static void pgss_store(const char *query, uint64 queryId,
|
static void pgss_store(const char *query, uint64 queryId,
|
||||||
int query_location, int query_len,
|
int query_location, int query_len,
|
||||||
pgssStoreKind kind,
|
pgssStoreKind kind,
|
||||||
@ -806,15 +814,13 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query, JumbleState *jstate)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Utility statements get queryId zero. We do this even in cases where
|
* Clear queryId for prepared statements related utility, as those will
|
||||||
* the statement contains an optimizable statement for which a queryId
|
* inherit from the underlying statement's one (except DEALLOCATE which is
|
||||||
* could be derived (such as EXPLAIN or DECLARE CURSOR). For such cases,
|
* entirely untracked).
|
||||||
* runtime control will first go through ProcessUtility and then the
|
|
||||||
* executor, and we don't want the executor hooks to do anything, since we
|
|
||||||
* are already measuring the statement's costs at the utility level.
|
|
||||||
*/
|
*/
|
||||||
if (query->utilityStmt)
|
if (query->utilityStmt)
|
||||||
{
|
{
|
||||||
|
if (pgss_track_utility && !PGSS_HANDLED_UTILITY(query->utilityStmt))
|
||||||
query->queryId = UINT64CONST(0);
|
query->queryId = UINT64CONST(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1057,6 +1063,23 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||||||
DestReceiver *dest, QueryCompletion *qc)
|
DestReceiver *dest, QueryCompletion *qc)
|
||||||
{
|
{
|
||||||
Node *parsetree = pstmt->utilityStmt;
|
Node *parsetree = pstmt->utilityStmt;
|
||||||
|
uint64 saved_queryId = pstmt->queryId;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Force utility statements to get queryId zero. We do this even in cases
|
||||||
|
* where the statement contains an optimizable statement for which a
|
||||||
|
* queryId could be derived (such as EXPLAIN or DECLARE CURSOR). For such
|
||||||
|
* cases, runtime control will first go through ProcessUtility and then the
|
||||||
|
* executor, and we don't want the executor hooks to do anything, since we
|
||||||
|
* are already measuring the statement's costs at the utility level.
|
||||||
|
*
|
||||||
|
* Note that this is only done if pg_stat_statements is enabled and
|
||||||
|
* configured to track utility statements, in the unlikely possibility
|
||||||
|
* that user configured another extension to handle utility statements
|
||||||
|
* only.
|
||||||
|
*/
|
||||||
|
if (pgss_enabled(exec_nested_level) && pgss_track_utility)
|
||||||
|
pstmt->queryId = UINT64CONST(0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's an EXECUTE statement, we don't track it and don't increment the
|
* If it's an EXECUTE statement, we don't track it and don't increment the
|
||||||
@ -1073,9 +1096,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||||||
* Likewise, we don't track execution of DEALLOCATE.
|
* Likewise, we don't track execution of DEALLOCATE.
|
||||||
*/
|
*/
|
||||||
if (pgss_track_utility && pgss_enabled(exec_nested_level) &&
|
if (pgss_track_utility && pgss_enabled(exec_nested_level) &&
|
||||||
!IsA(parsetree, ExecuteStmt) &&
|
PGSS_HANDLED_UTILITY(parsetree))
|
||||||
!IsA(parsetree, PrepareStmt) &&
|
|
||||||
!IsA(parsetree, DeallocateStmt))
|
|
||||||
{
|
{
|
||||||
instr_time start;
|
instr_time start;
|
||||||
instr_time duration;
|
instr_time duration;
|
||||||
@ -1130,7 +1151,7 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||||||
WalUsageAccumDiff(&walusage, &pgWalUsage, &walusage_start);
|
WalUsageAccumDiff(&walusage, &pgWalUsage, &walusage_start);
|
||||||
|
|
||||||
pgss_store(queryString,
|
pgss_store(queryString,
|
||||||
0, /* signal that it's a utility stmt */
|
saved_queryId,
|
||||||
pstmt->stmt_location,
|
pstmt->stmt_location,
|
||||||
pstmt->stmt_len,
|
pstmt->stmt_len,
|
||||||
PGSS_EXEC,
|
PGSS_EXEC,
|
||||||
@ -1153,23 +1174,12 @@ pgss_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Given an arbitrarily long query string, produce a hash for the purposes of
|
|
||||||
* identifying the query, without normalizing constants. Used when hashing
|
|
||||||
* utility statements.
|
|
||||||
*/
|
|
||||||
static uint64
|
|
||||||
pgss_hash_string(const char *str, int len)
|
|
||||||
{
|
|
||||||
return DatumGetUInt64(hash_any_extended((const unsigned char *) str,
|
|
||||||
len, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Store some statistics for a statement.
|
* Store some statistics for a statement.
|
||||||
*
|
*
|
||||||
* If queryId is 0 then this is a utility statement and we should compute
|
* If queryId is 0 then this is a utility statement for which we couldn't
|
||||||
* a suitable queryId internally.
|
* compute a queryId during parse analysis, and we should compute a suitable
|
||||||
|
* queryId internally.
|
||||||
*
|
*
|
||||||
* If jstate is not NULL then we're trying to create an entry for which
|
* If jstate is not NULL then we're trying to create an entry for which
|
||||||
* we have no statistics as yet; we just want to record the normalized
|
* we have no statistics as yet; we just want to record the normalized
|
||||||
@ -1199,53 +1209,19 @@ pgss_store(const char *query, uint64 queryId,
|
|||||||
if (!pgss || !pgss_hash)
|
if (!pgss || !pgss_hash)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Nothing to do if compute_query_id isn't enabled and no other module
|
||||||
|
* computed a query identifier.
|
||||||
|
*/
|
||||||
|
if (queryId == UINT64CONST(0))
|
||||||
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Confine our attention to the relevant part of the string, if the query
|
* Confine our attention to the relevant part of the string, if the query
|
||||||
* is a portion of a multi-statement source string.
|
* is a portion of a multi-statement source string, and update query
|
||||||
*
|
* location and length if needed.
|
||||||
* First apply starting offset, unless it's -1 (unknown).
|
|
||||||
*/
|
*/
|
||||||
if (query_location >= 0)
|
query = CleanQuerytext(query, &query_location, &query_len);
|
||||||
{
|
|
||||||
Assert(query_location <= strlen(query));
|
|
||||||
query += query_location;
|
|
||||||
/* Length of 0 (or -1) means "rest of string" */
|
|
||||||
if (query_len <= 0)
|
|
||||||
query_len = strlen(query);
|
|
||||||
else
|
|
||||||
Assert(query_len <= strlen(query));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* If query location is unknown, distrust query_len as well */
|
|
||||||
query_location = 0;
|
|
||||||
query_len = strlen(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Discard leading and trailing whitespace, too. Use scanner_isspace()
|
|
||||||
* not libc's isspace(), because we want to match the lexer's behavior.
|
|
||||||
*/
|
|
||||||
while (query_len > 0 && scanner_isspace(query[0]))
|
|
||||||
query++, query_location++, query_len--;
|
|
||||||
while (query_len > 0 && scanner_isspace(query[query_len - 1]))
|
|
||||||
query_len--;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For utility statements, we just hash the query string to get an ID.
|
|
||||||
*/
|
|
||||||
if (queryId == UINT64CONST(0))
|
|
||||||
{
|
|
||||||
queryId = pgss_hash_string(query, query_len);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we are unlucky enough to get a hash of zero(invalid), use
|
|
||||||
* queryID as 2 instead, queryID 1 is already in use for normal
|
|
||||||
* statements.
|
|
||||||
*/
|
|
||||||
if (queryId == UINT64CONST(0))
|
|
||||||
queryId = UINT64CONST(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set up key for hashtable search */
|
/* Set up key for hashtable search */
|
||||||
key.userid = GetUserId();
|
key.userid = GetUserId();
|
||||||
|
@ -7004,6 +7004,15 @@ local0.* /var/log/postgresql
|
|||||||
session processes</entry>
|
session processes</entry>
|
||||||
<entry>no</entry>
|
<entry>no</entry>
|
||||||
</row>
|
</row>
|
||||||
|
<row>
|
||||||
|
<entry><literal>%Q</literal></entry>
|
||||||
|
<entry>query identifier of the current query. Query
|
||||||
|
identifiers are not computed by default, so this field
|
||||||
|
will be zero unless <xref linkend="guc-compute-query-id"/>
|
||||||
|
parameter is enabled or a third-party module that computes
|
||||||
|
query identifiers is configured.</entry>
|
||||||
|
<entry>yes</entry>
|
||||||
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry><literal>%%</literal></entry>
|
<entry><literal>%%</literal></entry>
|
||||||
<entry>Literal <literal>%</literal></entry>
|
<entry>Literal <literal>%</literal></entry>
|
||||||
@ -7480,8 +7489,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Enables the collection of information on the currently
|
Enables the collection of information on the currently
|
||||||
executing command of each session, along with the time when
|
executing command of each session, along with its identifier and the
|
||||||
that command began execution. This parameter is on by
|
time when that command began execution. This parameter is on by
|
||||||
default. Note that even when enabled, this information is not
|
default. Note that even when enabled, this information is not
|
||||||
visible to all users, only to superusers and the user owning
|
visible to all users, only to superusers and the user owning
|
||||||
the session being reported on, so it should not represent a
|
the session being reported on, so it should not represent a
|
||||||
@ -7630,12 +7639,16 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
|
|||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Enables in-core computation of a query identifier. The <xref
|
Enables in-core computation of a query identifier.
|
||||||
linkend="pgstatstatements"/> extension requires a query identifier
|
Query identifiers can be displayed in the <link
|
||||||
to be computed. Note that an external module can alternatively
|
linkend="monitoring-pg-stat-activity-view"><structname>pg_stat_activity</structname></link>
|
||||||
be used if the in-core query identifier computation method
|
view, using <command>EXPLAIN</command>, or emitted in the log if
|
||||||
isn't acceptable. In this case, in-core computation should
|
configured via the <xref linkend="guc-log-line-prefix"/> parameter.
|
||||||
remain disabled. The default is <literal>off</literal>.
|
The <xref linkend="pgstatstatements"/> extension also requires a query
|
||||||
|
identifier to be computed. Note that an external module can
|
||||||
|
alternatively be used if the in-core query identifier computation
|
||||||
|
specification isn't acceptable. In this case, in-core computation
|
||||||
|
must be disabled. The default is <literal>off</literal>.
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
|
@ -910,6 +910,22 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
|
|||||||
</para></entry>
|
</para></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry role="catalog_table_entry"><para role="column_definition">
|
||||||
|
<structfield>queryid</structfield> <type>bigint</type>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
Identifier of this backend's most recent query. If
|
||||||
|
<structfield>state</structfield> is <literal>active</literal> this
|
||||||
|
field shows the identifier of the currently executing query. In
|
||||||
|
all other states, it shows the identifier of last query that was
|
||||||
|
executed. Query identifiers are not computed by default so this
|
||||||
|
field will be null unless <xref linkend="guc-compute-query-id"/>
|
||||||
|
parameter is enabled or a third-party module that computes query
|
||||||
|
identifiers is configured.
|
||||||
|
</para></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry role="catalog_table_entry"><para role="column_definition">
|
<entry role="catalog_table_entry"><para role="column_definition">
|
||||||
<structfield>query</structfield> <type>text</type>
|
<structfield>query</structfield> <type>text</type>
|
||||||
|
@ -136,8 +136,10 @@ ROLLBACK;
|
|||||||
the output column list for each node in the plan tree, schema-qualify
|
the output column list for each node in the plan tree, schema-qualify
|
||||||
table and function names, always label variables in expressions with
|
table and function names, always label variables in expressions with
|
||||||
their range table alias, and always print the name of each trigger for
|
their range table alias, and always print the name of each trigger for
|
||||||
which statistics are displayed. This parameter defaults to
|
which statistics are displayed. The query identifier will also be
|
||||||
<literal>FALSE</literal>.
|
displayed if one has been computed, see <xref
|
||||||
|
linkend="guc-compute-query-id"/> for more details. This parameter
|
||||||
|
defaults to <literal>FALSE</literal>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
@ -833,6 +833,7 @@ CREATE VIEW pg_stat_activity AS
|
|||||||
S.state,
|
S.state,
|
||||||
S.backend_xid,
|
S.backend_xid,
|
||||||
s.backend_xmin,
|
s.backend_xmin,
|
||||||
|
S.queryid,
|
||||||
S.query,
|
S.query,
|
||||||
S.backend_type
|
S.backend_type
|
||||||
FROM pg_stat_get_activity(NULL) AS S
|
FROM pg_stat_get_activity(NULL) AS S
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "nodes/extensible.h"
|
#include "nodes/extensible.h"
|
||||||
#include "nodes/makefuncs.h"
|
#include "nodes/makefuncs.h"
|
||||||
#include "nodes/nodeFuncs.h"
|
#include "nodes/nodeFuncs.h"
|
||||||
|
#include "parser/analyze.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "rewrite/rewriteHandler.h"
|
#include "rewrite/rewriteHandler.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
@ -165,6 +166,8 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
|
|||||||
{
|
{
|
||||||
ExplainState *es = NewExplainState();
|
ExplainState *es = NewExplainState();
|
||||||
TupOutputState *tstate;
|
TupOutputState *tstate;
|
||||||
|
JumbleState *jstate = NULL;
|
||||||
|
Query *query;
|
||||||
List *rewritten;
|
List *rewritten;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
bool timing_set = false;
|
bool timing_set = false;
|
||||||
@ -241,6 +244,13 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt,
|
|||||||
/* if the summary was not set explicitly, set default value */
|
/* if the summary was not set explicitly, set default value */
|
||||||
es->summary = (summary_set) ? es->summary : es->analyze;
|
es->summary = (summary_set) ? es->summary : es->analyze;
|
||||||
|
|
||||||
|
query = castNode(Query, stmt->query);
|
||||||
|
if (compute_query_id)
|
||||||
|
jstate = JumbleQuery(query, pstate->p_sourcetext);
|
||||||
|
|
||||||
|
if (post_parse_analyze_hook)
|
||||||
|
(*post_parse_analyze_hook) (pstate, query, jstate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse analysis was done already, but we still have to run the rule
|
* Parse analysis was done already, but we still have to run the rule
|
||||||
* rewriter. We do not do AcquireRewriteLocks: we assume the query either
|
* rewriter. We do not do AcquireRewriteLocks: we assume the query either
|
||||||
@ -600,6 +610,14 @@ ExplainOnePlan(PlannedStmt *plannedstmt, IntoClause *into, ExplainState *es,
|
|||||||
/* Create textual dump of plan tree */
|
/* Create textual dump of plan tree */
|
||||||
ExplainPrintPlan(es, queryDesc);
|
ExplainPrintPlan(es, queryDesc);
|
||||||
|
|
||||||
|
if (es->verbose && plannedstmt->queryId != UINT64CONST(0))
|
||||||
|
{
|
||||||
|
char buf[MAXINT8LEN+1];
|
||||||
|
|
||||||
|
pg_lltoa(plannedstmt->queryId, buf);
|
||||||
|
ExplainPropertyText("Query Identifier", buf, es);
|
||||||
|
}
|
||||||
|
|
||||||
/* Show buffer usage in planning */
|
/* Show buffer usage in planning */
|
||||||
if (bufusage)
|
if (bufusage)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
#include "storage/lmgr.h"
|
#include "storage/lmgr.h"
|
||||||
#include "tcop/utility.h"
|
#include "tcop/utility.h"
|
||||||
#include "utils/acl.h"
|
#include "utils/acl.h"
|
||||||
|
#include "utils/backend_status.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
#include "utils/memutils.h"
|
#include "utils/memutils.h"
|
||||||
#include "utils/partcache.h"
|
#include "utils/partcache.h"
|
||||||
@ -128,6 +129,14 @@ static void EvalPlanQualStart(EPQState *epqstate, Plan *planTree);
|
|||||||
void
|
void
|
||||||
ExecutorStart(QueryDesc *queryDesc, int eflags)
|
ExecutorStart(QueryDesc *queryDesc, int eflags)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* In some cases (e.g. an EXECUTE statement) a query execution will skip
|
||||||
|
* parse analysis, which means that the queryid won't be reported. Note
|
||||||
|
* that it's harmless to report the queryid multiple time, as the call will
|
||||||
|
* be ignored if the top level queryid has already been reported.
|
||||||
|
*/
|
||||||
|
pgstat_report_queryid(queryDesc->plannedstmt->queryId, false);
|
||||||
|
|
||||||
if (ExecutorStart_hook)
|
if (ExecutorStart_hook)
|
||||||
(*ExecutorStart_hook) (queryDesc, eflags);
|
(*ExecutorStart_hook) (queryDesc, eflags);
|
||||||
else
|
else
|
||||||
|
@ -175,7 +175,7 @@ ExecSerializePlan(Plan *plan, EState *estate)
|
|||||||
*/
|
*/
|
||||||
pstmt = makeNode(PlannedStmt);
|
pstmt = makeNode(PlannedStmt);
|
||||||
pstmt->commandType = CMD_SELECT;
|
pstmt->commandType = CMD_SELECT;
|
||||||
pstmt->queryId = UINT64CONST(0);
|
pstmt->queryId = pgstat_get_my_queryid();
|
||||||
pstmt->hasReturning = false;
|
pstmt->hasReturning = false;
|
||||||
pstmt->hasModifyingCTE = false;
|
pstmt->hasModifyingCTE = false;
|
||||||
pstmt->canSetTag = true;
|
pstmt->canSetTag = true;
|
||||||
@ -1421,8 +1421,9 @@ ParallelQueryMain(dsm_segment *seg, shm_toc *toc)
|
|||||||
/* Setting debug_query_string for individual workers */
|
/* Setting debug_query_string for individual workers */
|
||||||
debug_query_string = queryDesc->sourceText;
|
debug_query_string = queryDesc->sourceText;
|
||||||
|
|
||||||
/* Report workers' query for monitoring purposes */
|
/* Report workers' query and queryId for monitoring purposes */
|
||||||
pgstat_report_activity(STATE_RUNNING, debug_query_string);
|
pgstat_report_activity(STATE_RUNNING, debug_query_string);
|
||||||
|
pgstat_report_queryid(queryDesc->plannedstmt->queryId, false);
|
||||||
|
|
||||||
/* Attach to the dynamic shared memory area. */
|
/* Attach to the dynamic shared memory area. */
|
||||||
area_space = shm_toc_lookup(toc, PARALLEL_KEY_DSA, false);
|
area_space = shm_toc_lookup(toc, PARALLEL_KEY_DSA, false);
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "parser/parse_type.h"
|
#include "parser/parse_type.h"
|
||||||
#include "parser/parsetree.h"
|
#include "parser/parsetree.h"
|
||||||
#include "rewrite/rewriteManip.h"
|
#include "rewrite/rewriteManip.h"
|
||||||
|
#include "utils/backend_status.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/guc.h"
|
#include "utils/guc.h"
|
||||||
#include "utils/queryjumble.h"
|
#include "utils/queryjumble.h"
|
||||||
@ -130,6 +131,8 @@ parse_analyze(RawStmt *parseTree, const char *sourceText,
|
|||||||
|
|
||||||
free_parsestate(pstate);
|
free_parsestate(pstate);
|
||||||
|
|
||||||
|
pgstat_report_queryid(query->queryId, false);
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +170,8 @@ parse_analyze_varparams(RawStmt *parseTree, const char *sourceText,
|
|||||||
|
|
||||||
free_parsestate(pstate);
|
free_parsestate(pstate);
|
||||||
|
|
||||||
|
pgstat_report_queryid(query->queryId, false);
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,6 +695,8 @@ pg_analyze_and_rewrite_params(RawStmt *parsetree,
|
|||||||
|
|
||||||
free_parsestate(pstate);
|
free_parsestate(pstate);
|
||||||
|
|
||||||
|
pgstat_report_queryid(query->queryId, false);
|
||||||
|
|
||||||
if (log_parser_stats)
|
if (log_parser_stats)
|
||||||
ShowUsage("PARSE ANALYSIS STATISTICS");
|
ShowUsage("PARSE ANALYSIS STATISTICS");
|
||||||
|
|
||||||
@ -913,6 +915,7 @@ pg_plan_queries(List *querytrees, const char *query_string, int cursorOptions,
|
|||||||
stmt->utilityStmt = query->utilityStmt;
|
stmt->utilityStmt = query->utilityStmt;
|
||||||
stmt->stmt_location = query->stmt_location;
|
stmt->stmt_location = query->stmt_location;
|
||||||
stmt->stmt_len = query->stmt_len;
|
stmt->stmt_len = query->stmt_len;
|
||||||
|
stmt->queryId = query->queryId;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1029,6 +1032,8 @@ exec_simple_query(const char *query_string)
|
|||||||
DestReceiver *receiver;
|
DestReceiver *receiver;
|
||||||
int16 format;
|
int16 format;
|
||||||
|
|
||||||
|
pgstat_report_queryid(0, true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the command name for use in status display (it also becomes the
|
* Get the command name for use in status display (it also becomes the
|
||||||
* default completion tag, down inside PortalRun). Set ps_status and
|
* default completion tag, down inside PortalRun). Set ps_status and
|
||||||
|
@ -544,6 +544,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
|
|||||||
beentry->st_activity_start_timestamp = 0;
|
beentry->st_activity_start_timestamp = 0;
|
||||||
/* st_xact_start_timestamp and wait_event_info are also disabled */
|
/* st_xact_start_timestamp and wait_event_info are also disabled */
|
||||||
beentry->st_xact_start_timestamp = 0;
|
beentry->st_xact_start_timestamp = 0;
|
||||||
|
beentry->st_queryid = UINT64CONST(0);
|
||||||
proc->wait_event_info = 0;
|
proc->wait_event_info = 0;
|
||||||
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
||||||
}
|
}
|
||||||
@ -598,6 +599,14 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
|
|||||||
beentry->st_state = state;
|
beentry->st_state = state;
|
||||||
beentry->st_state_start_timestamp = current_timestamp;
|
beentry->st_state_start_timestamp = current_timestamp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If a new query is started, we reset the query identifier as it'll only
|
||||||
|
* be known after parse analysis, to avoid reporting last query's
|
||||||
|
* identifier.
|
||||||
|
*/
|
||||||
|
if (state == STATE_RUNNING)
|
||||||
|
beentry->st_queryid = UINT64CONST(0);
|
||||||
|
|
||||||
if (cmd_str != NULL)
|
if (cmd_str != NULL)
|
||||||
{
|
{
|
||||||
memcpy((char *) beentry->st_activity_raw, cmd_str, len);
|
memcpy((char *) beentry->st_activity_raw, cmd_str, len);
|
||||||
@ -608,6 +617,46 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
|
|||||||
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------
|
||||||
|
* pgstat_report_queryid() -
|
||||||
|
*
|
||||||
|
* Called to update top-level query identifier.
|
||||||
|
* --------
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
pgstat_report_queryid(uint64 queryId, bool force)
|
||||||
|
{
|
||||||
|
volatile PgBackendStatus *beentry = MyBEEntry;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if track_activities is disabled, st_queryid should already have been
|
||||||
|
* reset
|
||||||
|
*/
|
||||||
|
if (!beentry || !pgstat_track_activities)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We only report the top-level query identifiers. The stored queryid is
|
||||||
|
* reset when a backend calls pgstat_report_activity(STATE_RUNNING), or
|
||||||
|
* with an explicit call to this function using the force flag. If the
|
||||||
|
* saved query identifier is not zero it means that it's not a top-level
|
||||||
|
* command, so ignore the one provided unless it's an explicit call to
|
||||||
|
* reset the identifier.
|
||||||
|
*/
|
||||||
|
if (beentry->st_queryid != 0 && !force)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update my status entry, following the protocol of bumping
|
||||||
|
* st_changecount before and after. We use a volatile pointer here to
|
||||||
|
* ensure the compiler doesn't try to get cute.
|
||||||
|
*/
|
||||||
|
PGSTAT_BEGIN_WRITE_ACTIVITY(beentry);
|
||||||
|
beentry->st_queryid = queryId;
|
||||||
|
PGSTAT_END_WRITE_ACTIVITY(beentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* pgstat_report_appname() -
|
* pgstat_report_appname() -
|
||||||
*
|
*
|
||||||
@ -972,6 +1021,25 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ----------
|
||||||
|
* pgstat_get_my_queryid() -
|
||||||
|
*
|
||||||
|
* Return current backend's query identifier.
|
||||||
|
*/
|
||||||
|
uint64
|
||||||
|
pgstat_get_my_queryid(void)
|
||||||
|
{
|
||||||
|
if (!MyBEEntry)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* There's no need for a look around pgstat_begin_read_activity /
|
||||||
|
* pgstat_end_read_activity here as it's only called from
|
||||||
|
* pg_stat_get_activity which is already protected, or from the same
|
||||||
|
* backend which mean that there won't be concurrent write.
|
||||||
|
*/
|
||||||
|
return MyBEEntry->st_queryid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
* pgstat_fetch_stat_beentry() -
|
* pgstat_fetch_stat_beentry() -
|
||||||
|
@ -569,7 +569,7 @@ pg_stat_get_progress_info(PG_FUNCTION_ARGS)
|
|||||||
Datum
|
Datum
|
||||||
pg_stat_get_activity(PG_FUNCTION_ARGS)
|
pg_stat_get_activity(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
#define PG_STAT_GET_ACTIVITY_COLS 29
|
#define PG_STAT_GET_ACTIVITY_COLS 30
|
||||||
int num_backends = pgstat_fetch_stat_numbackends();
|
int num_backends = pgstat_fetch_stat_numbackends();
|
||||||
int curr_backend;
|
int curr_backend;
|
||||||
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
|
int pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
|
||||||
@ -914,6 +914,10 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
|
|||||||
values[27] = BoolGetDatum(false); /* GSS Encryption not in
|
values[27] = BoolGetDatum(false); /* GSS Encryption not in
|
||||||
* use */
|
* use */
|
||||||
}
|
}
|
||||||
|
if (beentry->st_queryid == 0)
|
||||||
|
nulls[29] = true;
|
||||||
|
else
|
||||||
|
values[29] = DatumGetUInt64(beentry->st_queryid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -941,6 +945,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
|
|||||||
nulls[26] = true;
|
nulls[26] = true;
|
||||||
nulls[27] = true;
|
nulls[27] = true;
|
||||||
nulls[28] = true;
|
nulls[28] = true;
|
||||||
|
nulls[29] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
|
||||||
|
@ -2714,6 +2714,14 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
|
|||||||
else
|
else
|
||||||
appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode));
|
appendStringInfoString(buf, unpack_sql_state(edata->sqlerrcode));
|
||||||
break;
|
break;
|
||||||
|
case 'Q':
|
||||||
|
if (padding != 0)
|
||||||
|
appendStringInfo(buf, "%*ld", padding,
|
||||||
|
pgstat_get_my_queryid());
|
||||||
|
else
|
||||||
|
appendStringInfo(buf, "%ld",
|
||||||
|
pgstat_get_my_queryid());
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
/* format error - ignore it */
|
/* format error - ignore it */
|
||||||
break;
|
break;
|
||||||
|
@ -543,6 +543,7 @@
|
|||||||
# %t = timestamp without milliseconds
|
# %t = timestamp without milliseconds
|
||||||
# %m = timestamp with milliseconds
|
# %m = timestamp with milliseconds
|
||||||
# %n = timestamp with milliseconds (as a Unix epoch)
|
# %n = timestamp with milliseconds (as a Unix epoch)
|
||||||
|
# %Q = query ID (0 if none or not computed)
|
||||||
# %i = command tag
|
# %i = command tag
|
||||||
# %e = SQL state
|
# %e = SQL state
|
||||||
# %c = session ID
|
# %c = session ID
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
#define JUMBLE_SIZE 1024 /* query serialization buffer size */
|
#define JUMBLE_SIZE 1024 /* query serialization buffer size */
|
||||||
|
|
||||||
static uint64 compute_utility_queryid(const char *str, int query_len);
|
static uint64 compute_utility_queryid(const char *str, int query_location, int query_len);
|
||||||
static void AppendJumble(JumbleState *jstate,
|
static void AppendJumble(JumbleState *jstate,
|
||||||
const unsigned char *item, Size size);
|
const unsigned char *item, Size size);
|
||||||
static void JumbleQueryInternal(JumbleState *jstate, Query *query);
|
static void JumbleQueryInternal(JumbleState *jstate, Query *query);
|
||||||
@ -97,17 +97,9 @@ JumbleQuery(Query *query, const char *querytext)
|
|||||||
JumbleState *jstate = NULL;
|
JumbleState *jstate = NULL;
|
||||||
if (query->utilityStmt)
|
if (query->utilityStmt)
|
||||||
{
|
{
|
||||||
const char *sql;
|
query->queryId = compute_utility_queryid(querytext,
|
||||||
int query_location = query->stmt_location;
|
query->stmt_location,
|
||||||
int query_len = query->stmt_len;
|
query->stmt_len);
|
||||||
|
|
||||||
/*
|
|
||||||
* Confine our attention to the relevant part of the string, if the
|
|
||||||
* query is a portion of a multi-statement source string.
|
|
||||||
*/
|
|
||||||
sql = CleanQuerytext(querytext, &query_location, &query_len);
|
|
||||||
|
|
||||||
query->queryId = compute_utility_queryid(sql, query_len);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -143,11 +135,18 @@ JumbleQuery(Query *query, const char *querytext)
|
|||||||
* Compute a query identifier for the given utility query string.
|
* Compute a query identifier for the given utility query string.
|
||||||
*/
|
*/
|
||||||
static uint64
|
static uint64
|
||||||
compute_utility_queryid(const char *str, int query_len)
|
compute_utility_queryid(const char *query_text, int query_location, int query_len)
|
||||||
{
|
{
|
||||||
uint64 queryId;
|
uint64 queryId;
|
||||||
|
const char *sql;
|
||||||
|
|
||||||
queryId = DatumGetUInt64(hash_any_extended((const unsigned char *) str,
|
/*
|
||||||
|
* Confine our attention to the relevant part of the string, if the
|
||||||
|
* query is a portion of a multi-statement source string.
|
||||||
|
*/
|
||||||
|
sql = CleanQuerytext(query_text, &query_location, &query_len);
|
||||||
|
|
||||||
|
queryId = DatumGetUInt64(hash_any_extended((const unsigned char *) sql,
|
||||||
query_len, 0));
|
query_len, 0));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 202104062
|
#define CATALOG_VERSION_NO 202104071
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -5278,9 +5278,9 @@
|
|||||||
proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
|
proname => 'pg_stat_get_activity', prorows => '100', proisstrict => 'f',
|
||||||
proretset => 't', provolatile => 's', proparallel => 'r',
|
proretset => 't', provolatile => 's', proparallel => 'r',
|
||||||
prorettype => 'record', proargtypes => 'int4',
|
prorettype => 'record', proargtypes => 'int4',
|
||||||
proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4}',
|
proallargtypes => '{int4,oid,int4,oid,text,text,text,text,text,timestamptz,timestamptz,timestamptz,timestamptz,inet,text,int4,xid,xid,text,bool,text,text,int4,text,numeric,text,bool,text,bool,int4,int8}',
|
||||||
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
|
proargmodes => '{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}',
|
||||||
proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid}',
|
proargnames => '{pid,datid,pid,usesysid,application_name,state,query,wait_event_type,wait_event,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,backend_type,ssl,sslversion,sslcipher,sslbits,ssl_client_dn,ssl_client_serial,ssl_issuer_dn,gss_auth,gss_princ,gss_enc,leader_pid,queryid}',
|
||||||
prosrc => 'pg_stat_get_activity' },
|
prosrc => 'pg_stat_get_activity' },
|
||||||
{ oid => '3318',
|
{ oid => '3318',
|
||||||
descr => 'statistics: information about progress of backends running maintenance command',
|
descr => 'statistics: information about progress of backends running maintenance command',
|
||||||
|
@ -165,6 +165,9 @@ typedef struct PgBackendStatus
|
|||||||
ProgressCommandType st_progress_command;
|
ProgressCommandType st_progress_command;
|
||||||
Oid st_progress_command_target;
|
Oid st_progress_command_target;
|
||||||
int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
|
int64 st_progress_param[PGSTAT_NUM_PROGRESS_PARAM];
|
||||||
|
|
||||||
|
/* query identifier, optionally computed using post_parse_analyze_hook */
|
||||||
|
uint64 st_queryid;
|
||||||
} PgBackendStatus;
|
} PgBackendStatus;
|
||||||
|
|
||||||
|
|
||||||
@ -294,12 +297,14 @@ extern void pgstat_clear_backend_activity_snapshot(void);
|
|||||||
|
|
||||||
/* Activity reporting functions */
|
/* Activity reporting functions */
|
||||||
extern void pgstat_report_activity(BackendState state, const char *cmd_str);
|
extern void pgstat_report_activity(BackendState state, const char *cmd_str);
|
||||||
|
extern void pgstat_report_queryid(uint64 queryId, bool force);
|
||||||
extern void pgstat_report_tempfile(size_t filesize);
|
extern void pgstat_report_tempfile(size_t filesize);
|
||||||
extern void pgstat_report_appname(const char *appname);
|
extern void pgstat_report_appname(const char *appname);
|
||||||
extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
|
extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
|
||||||
extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
|
extern const char *pgstat_get_backend_current_activity(int pid, bool checkUser);
|
||||||
extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
|
extern const char *pgstat_get_crashed_backend_activity(int pid, char *buffer,
|
||||||
int buflen);
|
int buflen);
|
||||||
|
extern uint64 pgstat_get_my_queryid(void);
|
||||||
|
|
||||||
|
|
||||||
/* ----------
|
/* ----------
|
||||||
|
@ -17,7 +17,7 @@ begin
|
|||||||
for ln in execute $1
|
for ln in execute $1
|
||||||
loop
|
loop
|
||||||
-- Replace any numeric word with just 'N'
|
-- Replace any numeric word with just 'N'
|
||||||
ln := regexp_replace(ln, '\m\d+\M', 'N', 'g');
|
ln := regexp_replace(ln, '-?\m\d+\M', 'N', 'g');
|
||||||
-- In sort output, the above won't match units-suffixed numbers
|
-- In sort output, the above won't match units-suffixed numbers
|
||||||
ln := regexp_replace(ln, '\m\d+kB', 'NkB', 'g');
|
ln := regexp_replace(ln, '\m\d+kB', 'NkB', 'g');
|
||||||
-- Ignore text-mode buffers output because it varies depending
|
-- Ignore text-mode buffers output because it varies depending
|
||||||
@ -477,3 +477,12 @@ select jsonb_pretty(
|
|||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
rollback;
|
rollback;
|
||||||
|
set compute_query_id = on;
|
||||||
|
select explain_filter('explain (verbose) select 1');
|
||||||
|
explain_filter
|
||||||
|
----------------------------------------
|
||||||
|
Result (cost=N.N..N.N rows=N width=N)
|
||||||
|
Output: N
|
||||||
|
Query Identifier: N
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
@ -1762,9 +1762,10 @@ pg_stat_activity| SELECT s.datid,
|
|||||||
s.state,
|
s.state,
|
||||||
s.backend_xid,
|
s.backend_xid,
|
||||||
s.backend_xmin,
|
s.backend_xmin,
|
||||||
|
s.queryid,
|
||||||
s.query,
|
s.query,
|
||||||
s.backend_type
|
s.backend_type
|
||||||
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
|
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, queryid)
|
||||||
LEFT JOIN pg_database d ON ((s.datid = d.oid)))
|
LEFT JOIN pg_database d ON ((s.datid = d.oid)))
|
||||||
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
|
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
|
||||||
pg_stat_all_indexes| SELECT c.oid AS relid,
|
pg_stat_all_indexes| SELECT c.oid AS relid,
|
||||||
@ -1876,7 +1877,7 @@ pg_stat_gssapi| SELECT s.pid,
|
|||||||
s.gss_auth AS gss_authenticated,
|
s.gss_auth AS gss_authenticated,
|
||||||
s.gss_princ AS principal,
|
s.gss_princ AS principal,
|
||||||
s.gss_enc AS encrypted
|
s.gss_enc AS encrypted
|
||||||
FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
|
FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, queryid)
|
||||||
WHERE (s.client_port IS NOT NULL);
|
WHERE (s.client_port IS NOT NULL);
|
||||||
pg_stat_progress_analyze| SELECT s.pid,
|
pg_stat_progress_analyze| SELECT s.pid,
|
||||||
s.datid,
|
s.datid,
|
||||||
@ -2046,7 +2047,7 @@ pg_stat_replication| SELECT s.pid,
|
|||||||
w.sync_priority,
|
w.sync_priority,
|
||||||
w.sync_state,
|
w.sync_state,
|
||||||
w.reply_time
|
w.reply_time
|
||||||
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
|
FROM ((pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, queryid)
|
||||||
JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
|
JOIN pg_stat_get_wal_senders() w(pid, state, sent_lsn, write_lsn, flush_lsn, replay_lsn, write_lag, flush_lag, replay_lag, sync_priority, sync_state, reply_time) ON ((s.pid = w.pid)))
|
||||||
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
|
LEFT JOIN pg_authid u ON ((s.usesysid = u.oid)));
|
||||||
pg_stat_replication_slots| SELECT s.slot_name,
|
pg_stat_replication_slots| SELECT s.slot_name,
|
||||||
@ -2076,7 +2077,7 @@ pg_stat_ssl| SELECT s.pid,
|
|||||||
s.ssl_client_dn AS client_dn,
|
s.ssl_client_dn AS client_dn,
|
||||||
s.ssl_client_serial AS client_serial,
|
s.ssl_client_serial AS client_serial,
|
||||||
s.ssl_issuer_dn AS issuer_dn
|
s.ssl_issuer_dn AS issuer_dn
|
||||||
FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid)
|
FROM pg_stat_get_activity(NULL::integer) s(datid, pid, usesysid, application_name, state, query, wait_event_type, wait_event, xact_start, query_start, backend_start, state_change, client_addr, client_hostname, client_port, backend_xid, backend_xmin, backend_type, ssl, sslversion, sslcipher, sslbits, ssl_client_dn, ssl_client_serial, ssl_issuer_dn, gss_auth, gss_princ, gss_enc, leader_pid, queryid)
|
||||||
WHERE (s.client_port IS NOT NULL);
|
WHERE (s.client_port IS NOT NULL);
|
||||||
pg_stat_subscription| SELECT su.oid AS subid,
|
pg_stat_subscription| SELECT su.oid AS subid,
|
||||||
su.subname,
|
su.subname,
|
||||||
|
@ -19,7 +19,7 @@ begin
|
|||||||
for ln in execute $1
|
for ln in execute $1
|
||||||
loop
|
loop
|
||||||
-- Replace any numeric word with just 'N'
|
-- Replace any numeric word with just 'N'
|
||||||
ln := regexp_replace(ln, '\m\d+\M', 'N', 'g');
|
ln := regexp_replace(ln, '-?\m\d+\M', 'N', 'g');
|
||||||
-- In sort output, the above won't match units-suffixed numbers
|
-- In sort output, the above won't match units-suffixed numbers
|
||||||
ln := regexp_replace(ln, '\m\d+kB', 'NkB', 'g');
|
ln := regexp_replace(ln, '\m\d+kB', 'NkB', 'g');
|
||||||
-- Ignore text-mode buffers output because it varies depending
|
-- Ignore text-mode buffers output because it varies depending
|
||||||
@ -103,3 +103,6 @@ select jsonb_pretty(
|
|||||||
);
|
);
|
||||||
|
|
||||||
rollback;
|
rollback;
|
||||||
|
|
||||||
|
set compute_query_id = on;
|
||||||
|
select explain_filter('explain (verbose) select 1');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user