PG-186: Add support to monitor query execution plan.

pull/79/head
Ibrar Ahmed 2021-03-17 18:56:39 +05:00
parent aa0ca050d5
commit e0fc683810
18 changed files with 499 additions and 533 deletions

View File

@ -11,7 +11,7 @@ PGFILEDESC = "pg_stat_monitor - execution statistics of SQL statements"
LDFLAGS_SL += $(filter -lm, $(LIBS)) LDFLAGS_SL += $(filter -lm, $(LIBS))
REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_stat_monitor/pg_stat_monitor.conf --inputdir=regression REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_stat_monitor/pg_stat_monitor.conf --inputdir=regression
REGRESS = basic version guc user counters relations database top_query application_name cmd_type error rows REGRESS = basic version guc counters relations database top_query application_name cmd_type error rows
# Disabled because these tests require "shared_preload_libraries=pg_stat_statements", # Disabled because these tests require "shared_preload_libraries=pg_stat_statements",
# which typical installcheck users do not have (e.g. buildfarm clients). # which typical installcheck users do not have (e.g. buildfarm clients).

View File

@ -21,7 +21,6 @@
static pgssSharedState *pgss; static pgssSharedState *pgss;
static HTAB *pgss_hash; static HTAB *pgss_hash;
static HTAB *pgss_query_hash; static HTAB *pgss_query_hash;
static HTAB *pgss_plan_hash;
static HTAB* hash_init(const char *hash_name, int key_size, int entry_size, int hash_size); static HTAB* hash_init(const char *hash_name, int key_size, int entry_size, int hash_size);
@ -71,8 +70,7 @@ pgss_startup(void)
} }
pgss_hash = hash_init("pg_stat_monitor: bucket hashtable", sizeof(pgssHashKey), sizeof(pgssEntry), MAX_BUCKET_ENTRIES); pgss_hash = hash_init("pg_stat_monitor: bucket hashtable", sizeof(pgssHashKey), sizeof(pgssEntry), MAX_BUCKET_ENTRIES);
pgss_query_hash = hash_init("pg_stat_monitor: query hashtable", sizeof(pgssQueryHashKey), sizeof(pgssQueryEntry),500000); pgss_query_hash = hash_init("pg_stat_monitor: query hashtable", sizeof(pgssQueryHashKey), sizeof(pgssQueryEntry),MAX_BUCKET_ENTRIES);
pgss_plan_hash = hash_init("pg_stat_monitor: plan hashtable", sizeof(pgssPlanHashKey), sizeof(pgssPlanEntry), MAX_BUCKET_ENTRIES);
LWLockRelease(AddinShmemInitLock); LWLockRelease(AddinShmemInitLock);
@ -83,12 +81,6 @@ pgss_startup(void)
on_shmem_exit(pgss_shmem_shutdown, (Datum) 0); on_shmem_exit(pgss_shmem_shutdown, (Datum) 0);
} }
HTAB*
pgsm_get_plan_hash(void)
{
return pgss_plan_hash;
}
pgssSharedState* pgssSharedState*
pgsm_get_ss(void) pgsm_get_ss(void)
{ {
@ -101,6 +93,12 @@ pgsm_get_hash(void)
return pgss_hash; return pgss_hash;
} }
HTAB*
pgsm_get_query_hash(void)
{
return pgss_query_hash;
}
/* /*
* shmem_shutdown hook: Dump statistics into file. * shmem_shutdown hook: Dump statistics into file.
* *
@ -128,33 +126,11 @@ hash_memsize(void)
size = MAXALIGN(sizeof(pgssSharedState)); size = MAXALIGN(sizeof(pgssSharedState));
size += MAXALIGN(MAX_QUERY_BUF); size += MAXALIGN(MAX_QUERY_BUF);
size = add_size(size, hash_estimate_size(MAX_BUCKET_ENTRIES, sizeof(pgssEntry))); size = add_size(size, hash_estimate_size(MAX_BUCKET_ENTRIES, sizeof(pgssEntry)));
size = add_size(size, hash_estimate_size(MAX_BUCKET_ENTRIES, sizeof(pgssPlanEntry))); size = add_size(size, hash_estimate_size(MAX_BUCKET_ENTRIES, sizeof(pgssQueryEntry)));
size = add_size(size, hash_estimate_size(500000, sizeof(pgssQueryEntry)));
return size; return size;
} }
pgssPlanEntry *
hash_plan_entry_alloc(pgssSharedState *pgss, pgssPlanHashKey *key)
{
pgssPlanEntry *entry = NULL;
bool found = false;
if (hash_get_num_entries(pgss_plan_hash) >= MAX_BUCKET_ENTRIES)
return NULL;
/* Find or create an entry with desired hash code */
entry = (pgssPlanEntry *) hash_search(pgss_plan_hash, key, HASH_ENTER, &found);
if (!found)
{
memset(&entry->plan_info, 0, sizeof(PlanInfo));
SpinLockInit(&entry->mutex);
}
if (entry == NULL)
elog(FATAL, "%s", "pg_stat_monitor: out of memory");
return entry;
}
pgssEntry * pgssEntry *
hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key,int encoding) hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key,int encoding)
{ {
@ -163,7 +139,7 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key,int encoding)
if (hash_get_num_entries(pgss_hash) >= MAX_BUCKET_ENTRIES) if (hash_get_num_entries(pgss_hash) >= MAX_BUCKET_ENTRIES)
{ {
elog(DEBUG2, "%s", "pg_stat_monitor: out of memory"); elog(DEBUG1, "%s", "pg_stat_monitor: out of memory");
return NULL; return NULL;
} }
/* Find or create an entry with desired hash code */ /* Find or create an entry with desired hash code */
@ -181,7 +157,7 @@ hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key,int encoding)
entry->encoding = encoding; entry->encoding = encoding;
} }
if (entry == NULL) if (entry == NULL)
elog(FATAL, "%s", "pg_stat_monitor: out of memory"); elog(DEBUG1, "%s", "pg_stat_monitor: out of memory");
return entry; return entry;
} }
@ -199,7 +175,7 @@ hash_query_entry_dealloc(int bucket)
hash_seq_init(&hash_seq, pgss_query_hash); hash_seq_init(&hash_seq, pgss_query_hash);
while ((entry = hash_seq_search(&hash_seq)) != NULL) while ((entry = hash_seq_search(&hash_seq)) != NULL)
{ {
if (entry->key.bucket_id == bucket) if (entry->key.bucket_id == bucket || bucket < 0)
entry = hash_search(pgss_query_hash, &entry->key, HASH_REMOVE, NULL); entry = hash_search(pgss_query_hash, &entry->key, HASH_REMOVE, NULL);
} }
} }
@ -247,8 +223,8 @@ hash_entry_reset()
} }
/* Caller must accuire lock */ /* Caller must accuire lock */
bool pgssQueryEntry*
hash_create_query_entry(uint64 bucket_id, uint64 queryid) hash_create_query_entry(uint64 bucket_id, uint64 queryid, uint64 dbid, uint64 userid, uint64 ip)
{ {
pgssQueryHashKey key; pgssQueryHashKey key;
pgssQueryEntry *entry; pgssQueryEntry *entry;
@ -256,14 +232,17 @@ hash_create_query_entry(uint64 bucket_id, uint64 queryid)
key.queryid = queryid; key.queryid = queryid;
key.bucket_id = bucket_id; key.bucket_id = bucket_id;
key.dbid = dbid;
key.userid = userid;
key.ip = ip;
entry = (pgssQueryEntry *) hash_search(pgss_query_hash, &key, HASH_ENTER, &found); entry = (pgssQueryEntry *) hash_search(pgss_query_hash, &key, HASH_ENTER, &found);
return (entry != NULL); return entry;
} }
/* Caller must accuire lock */ /* Caller must accuire lock */
bool pgssQueryEntry*
hash_find_query_entry(uint64 bucket_id, uint64 queryid) hash_find_query_entry(uint64 bucket_id, uint64 queryid, uint64 dbid, uint64 userid, uint64 ip)
{ {
pgssQueryHashKey key; pgssQueryHashKey key;
pgssQueryEntry *entry; pgssQueryEntry *entry;
@ -271,10 +250,13 @@ hash_find_query_entry(uint64 bucket_id, uint64 queryid)
key.queryid = queryid; key.queryid = queryid;
key.bucket_id = bucket_id; key.bucket_id = bucket_id;
key.dbid = dbid;
key.userid = userid;
key.ip = ip;
/* Lookup the hash table entry with shared lock. */ /* Lookup the hash table entry with shared lock. */
entry = (pgssQueryEntry *) hash_search(pgss_query_hash, &key, HASH_FIND, &found); entry = (pgssQueryEntry *) hash_search(pgss_query_hash, &key, HASH_FIND, &found);
return ((entry != NULL) && found); return entry;
} }
bool bool

View File

@ -25,19 +25,20 @@ SELECT string_to_array(get_histogram_timings(), ',');
$$ LANGUAGE SQL; $$ LANGUAGE SQL;
CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean, CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
OUT bucket int, -- 0 OUT bucket int8, -- 0
OUT userid oid, OUT userid oid,
OUT dbid oid, OUT dbid oid,
OUT client_ip int8, OUT client_ip int8,
OUT queryid text, -- 4 OUT queryid text, -- 4
OUT planid text, OUT planid text,
OUT top_queryid text,
OUT query text, OUT query text,
OUT query_plan text, OUT query_plan text,
OUT state int8,
OUT top_queryid text,
OUT application_name text, OUT application_name text,
OUT relations text, -- 10 OUT relations text, -- 11
OUT cmd_type int, OUT cmd_type int,
OUT elevel int, OUT elevel int,
OUT sqlcode TEXT, OUT sqlcode TEXT,
@ -57,8 +58,9 @@ CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
OUT plan_min_time float8, OUT plan_min_time float8,
OUT plan_max_time float8, OUT plan_max_time float8,
OUT plan_mean_time float8, OUT plan_mean_time float8,
OUT plan_stddev_time float8,
OUT shared_blks_hit int8, -- 28 OUT shared_blks_hit int8, -- 29
OUT shared_blks_read int8, OUT shared_blks_read int8,
OUT shared_blks_dirtied int8, OUT shared_blks_dirtied int8,
OUT shared_blks_written int8, OUT shared_blks_written int8,
@ -70,7 +72,7 @@ CREATE FUNCTION pg_stat_monitor_internal(IN showtext boolean,
OUT temp_blks_written int8, OUT temp_blks_written int8,
OUT blk_read_time float8, OUT blk_read_time float8,
OUT blk_write_time float8, OUT blk_write_time float8,
OUT resp_calls text, OUT resp_calls text, -- 41
OUT cpu_user_time float8, OUT cpu_user_time float8,
OUT cpu_sys_time float8, OUT cpu_sys_time float8,
OUT wal_records int8, OUT wal_records int8,
@ -81,6 +83,19 @@ RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pg_stat_monitor' AS 'MODULE_PATHNAME', 'pg_stat_monitor'
LANGUAGE C STRICT VOLATILE PARALLEL SAFE; LANGUAGE C STRICT VOLATILE PARALLEL SAFE;
CREATE OR REPLACE FUNCTION get_state(state int8) RETURNS TEXT AS
$$
SELECT
CASE
WHEN state = 0 THEN 'PARSED'
WHEN state = 1 THEN 'PLANNING'
WHEN state = 2 THEN 'EXECUTION FINISHED'
WHEN state = 3 THEN 'ERROR'
WHEN state = 4 THEN 'FINISHED'
END
$$
LANGUAGE SQL PARALLEL SAFE;
CREATE or REPLACE FUNCTION get_cmd_type (cmd_type INTEGER) RETURNS TEXT AS CREATE or REPLACE FUNCTION get_cmd_type (cmd_type INTEGER) RETURNS TEXT AS
$$ $$
SELECT SELECT
@ -169,7 +184,9 @@ CREATE VIEW pg_stat_monitor AS SELECT
round(cpu_sys_time::numeric, 4) as cpu_sys_time, round(cpu_sys_time::numeric, 4) as cpu_sys_time,
wal_records, wal_records,
wal_fpi, wal_fpi,
wal_bytes wal_bytes,
state,
get_state(state) as state_value
FROM pg_stat_monitor_internal(TRUE) p, pg_database d WHERE dbid = oid FROM pg_stat_monitor_internal(TRUE) p, pg_database d WHERE dbid = oid
ORDER BY bucket_start_time; ORDER BY bucket_start_time;

View File

@ -1,4 +1,3 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* pg_stat_monitor.c * pg_stat_monitor.c
@ -22,7 +21,7 @@
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
#define BUILD_VERSION "devel" #define BUILD_VERSION "devel"
#define PG_STAT_STATEMENTS_COLS 49 /* maximum of above */ #define PG_STAT_STATEMENTS_COLS 51 /* maximum of above */
#define PGSM_TEXT_FILE "/tmp/pg_stat_monitor_query" #define PGSM_TEXT_FILE "/tmp/pg_stat_monitor_query"
#define PGUNSIXBIT(val) (((val) & 0x3F) + '0') #define PGUNSIXBIT(val) (((val) & 0x3F) + '0')
@ -52,8 +51,6 @@ do \
void _PG_init(void); void _PG_init(void);
void _PG_fini(void); void _PG_fini(void);
int64 v = 5631;
/*---- Initicalization Function Declarations ----*/ /*---- Initicalization Function Declarations ----*/
void _PG_init(void); void _PG_init(void);
void _PG_fini(void); void _PG_fini(void);
@ -72,10 +69,7 @@ static bool system_init = false;
static struct rusage rusage_start; static struct rusage rusage_start;
static struct rusage rusage_end; static struct rusage rusage_end;
static unsigned char *pgss_qbuf[MAX_BUCKETS]; static unsigned char *pgss_qbuf[MAX_BUCKETS];
static char *pgss_explain(QueryDesc *queryDesc); static char *pgss_explain(QueryDesc *queryDesc);
static bool pgss_get_plan(uint64 query_hash, PlanInfo *plan_info);
static bool pgss_store_plan(uint64 query_hash, PlanInfo *plan_info);
static int get_histogram_bucket(double q_time); static int get_histogram_bucket(double q_time);
static bool IsSystemInitialized(void); static bool IsSystemInitialized(void);
@ -141,7 +135,14 @@ static uint64 pgss_hash_string(const char *str, int len);
char *unpack_sql_state(int sql_state); char *unpack_sql_state(int sql_state);
static void pgss_store_error(uint64 queryid, const char * query, ErrorData *edata); static void pgss_store_error(uint64 queryid, const char * query, ErrorData *edata);
static void pgss_store_query(uint64 queryid, const char * query, CmdType cmd_type, int query_location, int query_len, pgssJumbleState *jstate); static pgssQueryEntry *pgss_store_query_info(uint64 bucketid,
uint64 queryid,
uint64 dbid,
uint64 userid,
uint64 ip,
const char *query,
uint64 query_len,
pgssStoreKind kind);
static void pgss_store_utility(const char *query, static void pgss_store_utility(const char *query,
double total_time, double total_time,
@ -173,14 +174,20 @@ static void JumbleExpr(pgssJumbleState *jstate, Node *node);
static void RecordConstLocation(pgssJumbleState *jstate, int location); static void RecordConstLocation(pgssJumbleState *jstate, int location);
static char *generate_normalized_query(pgssJumbleState *jstate, const char *query, static char *generate_normalized_query(pgssJumbleState *jstate, const char *query,
int query_loc, int *query_len_p, int encoding); int query_loc, int *query_len_p, int encoding);
static void fill_in_constant_lengths(pgssJumbleState *jstate, const char *query, static void fill_in_constant_lengths(pgssJumbleState *jstate, const char *query, int query_loc);
int query_loc);
static int comp_location(const void *a, const void *b); static int comp_location(const void *a, const void *b);
static uint64 get_next_wbucket(pgssSharedState *pgss); static uint64 get_next_wbucket(pgssSharedState *pgss);
static void store_query(int bucket_id, uint64 queryid, const char *query, uint64 query_len); static void
static uint64 read_query(unsigned char *buf, uint64 queryid, char * query); pgss_store_query(uint64 queryid,
const char * query,
CmdType cmd_type,
int query_location,
int query_len,
pgssJumbleState *jstate,
pgssStoreKind kind);
static uint64 read_query(unsigned char *buf, uint64 bucketid, uint64 queryid, char * query);
int read_query_buffer(int bucket_id, uint64 queryid, char *query_txt); int read_query_buffer(int bucket_id, uint64 queryid, char *query_txt);
static uint64 get_query_id(pgssJumbleState *jstate, Query *query); static uint64 get_query_id(pgssJumbleState *jstate, Query *query);
@ -306,6 +313,7 @@ static void
pgss_post_parse_analyze(ParseState *pstate, Query *query) pgss_post_parse_analyze(ParseState *pstate, Query *query)
{ {
pgssJumbleState jstate; pgssJumbleState jstate;
pgssStoreKind kind = PGSS_PARSE;
if (prev_post_parse_analyze_hook) if (prev_post_parse_analyze_hook)
prev_post_parse_analyze_hook(pstate, query); prev_post_parse_analyze_hook(pstate, query);
@ -344,8 +352,9 @@ pgss_post_parse_analyze(ParseState *pstate, Query *query)
pstate->p_sourcetext, /* query */ pstate->p_sourcetext, /* query */
query->commandType, /* CmdType */ query->commandType, /* CmdType */
query->stmt_location, /* Query Location */ query->stmt_location, /* Query Location */
query->stmt_len, /* Quer Len */ query->stmt_len, /* Query Len */
&jstate); /* pgssJumbleState */ &jstate, /* pgssJumbleState */
kind); /*pgssStoreKind */
} }
/* /*
@ -355,7 +364,7 @@ static void
pgss_ExecutorStart(QueryDesc *queryDesc, int eflags) pgss_ExecutorStart(QueryDesc *queryDesc, int eflags)
{ {
if(getrusage(RUSAGE_SELF, &rusage_start) != 0) if(getrusage(RUSAGE_SELF, &rusage_start) != 0)
elog(WARNING, "pg_stat_monitor: failed to execute getrusage"); elog(DEBUG1, "pg_stat_monitor: failed to execute getrusage");
if (prev_ExecutorStart) if (prev_ExecutorStart)
prev_ExecutorStart(queryDesc, eflags); prev_ExecutorStart(queryDesc, eflags);
@ -438,55 +447,6 @@ pgss_ExecutorFinish(QueryDesc *queryDesc)
PG_END_TRY(); PG_END_TRY();
} }
static bool
pgss_get_plan(uint64 query_hash, PlanInfo *plan_info)
{
pgssPlanHashKey key;
pgssPlanEntry *entry;
HTAB *pgss_plan_hash = pgsm_get_plan_hash();
key.query_hash = query_hash;
entry = (pgssPlanEntry *) hash_search(pgss_plan_hash, &key, HASH_FIND, NULL);
if(entry)
{
memcpy(plan_info, &entry->plan_info, sizeof(PlanInfo));
return true;
}
return false;
}
static bool
pgss_store_plan(uint64 query_hash, PlanInfo *plan_info)
{
pgssPlanHashKey key;
pgssPlanEntry *entry;
HTAB *pgss_plan_hash = pgsm_get_plan_hash();
pgssSharedState *pgss = pgsm_get_ss();
bool found = true;
LWLockAcquire(pgss->lock, LW_SHARED);
/* Set up key for hashtable search */
key.query_hash = query_hash;
entry = (pgssPlanEntry *) hash_search(pgss_plan_hash, &key, HASH_FIND, NULL);
if (!entry)
{
entry = hash_plan_entry_alloc(pgss, &key);
if (entry == NULL)
{
LWLockRelease(pgss->lock);
return found;
}
found = false;
}
SpinLockAcquire(&entry->mutex);
memcpy(&entry->plan_info, plan_info, sizeof(PlanInfo));
SpinLockRelease(&entry->mutex);
LWLockRelease(pgss->lock);
return found;
}
static char * static char *
pgss_explain(QueryDesc *queryDesc) pgss_explain(QueryDesc *queryDesc)
{ {
@ -536,7 +496,7 @@ pgss_ExecutorEnd(QueryDesc *queryDesc)
*/ */
InstrEndLoop(queryDesc->totaltime); InstrEndLoop(queryDesc->totaltime);
if(getrusage(RUSAGE_SELF, &rusage_end) != 0) if(getrusage(RUSAGE_SELF, &rusage_end) != 0)
elog(WARNING, "pg_stat_monitor: failed to execute getrusage"); elog(DEBUG1, "pg_stat_monitor: failed to execute getrusage");
sys_info.utime = time_diff(rusage_end.ru_utime, rusage_start.ru_utime); sys_info.utime = time_diff(rusage_end.ru_utime, rusage_start.ru_utime);
sys_info.stime = time_diff(rusage_end.ru_stime, rusage_start.ru_stime); sys_info.stime = time_diff(rusage_end.ru_stime, rusage_start.ru_stime);
@ -626,6 +586,7 @@ pgss_planner_hook(Query *parse, const char *query_string, int cursorOptions, Par
WalUsage walusage_start; WalUsage walusage_start;
WalUsage walusage; WalUsage walusage;
memset(&plan_info, 0, sizeof(PlanInfo));
/* We need to track buffer usage as the planner can access them. */ /* We need to track buffer usage as the planner can access them. */
bufusage_start = pgBufferUsage; bufusage_start = pgBufferUsage;
@ -916,7 +877,8 @@ pgss_update_entry(pgssEntry *entry,
uint64 rows, uint64 rows,
BufferUsage *bufusage, BufferUsage *bufusage,
WalUsage *walusage, WalUsage *walusage,
bool reset) bool reset,
pgssStoreKind kind)
{ {
int index; int index;
char application_name[APPLICATIONNAME_LEN]; char application_name[APPLICATIONNAME_LEN];
@ -925,6 +887,8 @@ pgss_update_entry(pgssEntry *entry,
double old_mean; double old_mean;
int message_len = error_info ? strlen (error_info->message) : 0; int message_len = error_info ? strlen (error_info->message) : 0;
int sqlcode_len = error_info ? strlen (error_info->sqlcode) : 0; int sqlcode_len = error_info ? strlen (error_info->sqlcode) : 0;
int plan_text_len = plan_info ? strlen (plan_info->plan_text) : 0;
/* volatile block */ /* volatile block */
{ {
@ -934,6 +898,32 @@ pgss_update_entry(pgssEntry *entry,
if (reset) if (reset)
memset(&entry->counters, 0, sizeof(Counters)); memset(&entry->counters, 0, sizeof(Counters));
if (kind == PGSS_PLAN)
{
if (e->counters.plancalls.calls == 0)
e->counters.plancalls.usage = USAGE_INIT;
e->counters.plancalls.calls += 1;
e->counters.plantime.total_time += total_time;
if (e->counters.plancalls.calls == 1)
{
e->counters.plantime.min_time = total_time;
e->counters.plantime.max_time = total_time;
e->counters.plantime.mean_time = total_time;
}
/* Increment the counts, except when jstate is not NULL */
old_mean = e->counters.plantime.mean_time;
e->counters.plantime.mean_time += (total_time - old_mean) / e->counters.plancalls.calls;
e->counters.plantime.sum_var_time +=(total_time - old_mean) * (total_time - e->counters.plantime.mean_time);
/* calculate min and max time */
if (e->counters.plantime.min_time > total_time) e->counters.plantime.min_time = total_time;
if (e->counters.plantime.max_time < total_time) e->counters.plantime.max_time = total_time;
}
else
{
e->counters.state = kind;
if (e->counters.calls.calls == 0) if (e->counters.calls.calls == 0)
e->counters.calls.usage = USAGE_INIT; e->counters.calls.usage = USAGE_INIT;
e->counters.calls.calls += 1; e->counters.calls.calls += 1;
@ -957,7 +947,9 @@ pgss_update_entry(pgssEntry *entry,
index = get_histogram_bucket(total_time); index = get_histogram_bucket(total_time);
e->counters.resp_calls[index]++; e->counters.resp_calls[index]++;
}
_snprintf(e->counters.planinfo.plan_text, plan_info->plan_text, plan_text_len, PLAN_TEXT_LEN);
_snprintf(e->counters.info.application_name, application_name, application_name_len, APPLICATIONNAME_LEN); _snprintf(e->counters.info.application_name, application_name, application_name_len, APPLICATIONNAME_LEN);
e->counters.info.num_relations = pgss->num_relations; e->counters.info.num_relations = pgss->num_relations;
@ -1020,7 +1012,7 @@ pgss_get_entry(uint64 bucket_id,
uint64 dbid, uint64 dbid,
uint64 queryid, uint64 queryid,
uint64 ip, uint64 ip,
bool *found) uint64 planid)
{ {
pgssEntry *entry; pgssEntry *entry;
pgssHashKey key; pgssHashKey key;
@ -1032,12 +1024,11 @@ pgss_get_entry(uint64 bucket_id,
key.dbid = MyDatabaseId; key.dbid = MyDatabaseId;
key.queryid = queryid; key.queryid = queryid;
key.ip = pg_get_client_addr(); key.ip = pg_get_client_addr();
key.planid = planid;
entry = (pgssEntry *) hash_search(pgss_hash, &key, HASH_FIND, NULL); entry = (pgssEntry *) hash_search(pgss_hash, &key, HASH_FIND, NULL);
if(!entry) if(!entry)
{ {
if (found)
*found = false;
/* OK to create a new hashtable entry */ /* OK to create a new hashtable entry */
entry = hash_entry_alloc(pgss, &key, GetDatabaseEncoding()); entry = hash_entry_alloc(pgss, &key, GetDatabaseEncoding());
if (entry == NULL) if (entry == NULL)
@ -1053,7 +1044,8 @@ pgss_store_query(uint64 queryid,
CmdType cmd_type, CmdType cmd_type,
int query_location, int query_location,
int query_len, int query_len,
pgssJumbleState *jstate) pgssJumbleState *jstate,
pgssStoreKind kind)
{ {
char *norm_query = NULL; char *norm_query = NULL;
@ -1105,7 +1097,7 @@ pgss_store_query(uint64 queryid,
NULL, /* bufusage */ NULL, /* bufusage */
NULL, /* walusage */ NULL, /* walusage */
jstate, /* pgssJumbleState */ jstate, /* pgssJumbleState */
PGSS_EXEC); /* pgssStoreKind */ kind); /* pgssStoreKind */
} }
static void static void
@ -1117,7 +1109,7 @@ pgss_store_error(uint64 queryid,
error_info.elevel = edata->elevel; error_info.elevel = edata->elevel;
snprintf(error_info.message, ERROR_MESSAGE_LEN, "%s", edata->message); snprintf(error_info.message, ERROR_MESSAGE_LEN, "%s", edata->message);
snprintf(error_info.sqlcode, ERROR_MESSAGE_LEN, "%s", unpack_sql_state(edata->sqlerrcode)); snprintf(error_info.sqlcode, SQLCODE_LEN, "%s", unpack_sql_state(edata->sqlerrcode));
pgss_store(queryid, /* query id */ pgss_store(queryid, /* query id */
query, /* query text */ query, /* query text */
@ -1156,55 +1148,6 @@ pgss_store_utility(const char *query,
PGSS_EXEC); /* pgssStoreKind */ PGSS_EXEC); /* pgssStoreKind */
} }
static void
update_planinfo(PlanInfo *plan_info, pgssStoreKind kind, double total_time, uint64 userid, uint64 dbid, uint64 queryid, uint64 ip)
{
char str[64];
uint64 query_hash;
PlanInfo pi;
if (plan_info == NULL)
return;
snprintf(str, 64, "%08lx%08lX%08lX%08lX", userid, dbid, queryid, ip);
query_hash = DatumGetUInt64(hash_any_extended((const unsigned char*)str, strlen(str), 0));
if (pgss_get_plan(query_hash, &pi))
{
if (kind == PGSS_PLAN)
{
double old_mean = 0;
pi.plans += 1;
pi.time.total_time += total_time;
if (pi.plans == 0)
if (pi.plans == 1)
{
pi.time.min_time = total_time;
pi.time.max_time = total_time;
pi.time.mean_time = total_time;
}
/* Increment the counts, except when jstate is not NULL */
old_mean = pi.time.mean_time;
pi.time.mean_time += (total_time - old_mean) / pi.plans;
pi.time.sum_var_time +=(total_time - old_mean) * (total_time - pi.time.mean_time);
/* calculate min and max time */
if (pi.time.min_time > total_time) pi.time.min_time = total_time;
if (pi.time.max_time < total_time) pi.time.max_time = total_time;
pgss_store_plan(query_hash, &pi);
}
}
else
{
if (kind == PGSS_EXEC)
{
pgss_store_plan(query_hash, plan_info);
}
}
}
/* /*
* Store some statistics for a statement. * Store some statistics for a statement.
* *
@ -1229,11 +1172,14 @@ pgss_store(uint64 queryid,
pgssJumbleState *jstate, pgssJumbleState *jstate,
pgssStoreKind kind) pgssStoreKind kind)
{ {
int bucket_id;
pgssEntry *entry; pgssEntry *entry;
pgssSharedState *pgss = pgsm_get_ss(); pgssSharedState *pgss = pgsm_get_ss();
bool reset = false; bool reset = false;
bool found = true; uint64 bucketid;
uint64 userid = GetUserId();
uint64 dbid = MyDatabaseId;
uint64 ip = pg_get_client_addr();
uint64 planid = plan_info ? plan_info->planid: 0;
/* Monitoring is disabled */ /* Monitoring is disabled */
if (!PGSM_ENABLED) if (!PGSM_ENABLED)
@ -1245,30 +1191,45 @@ pgss_store(uint64 queryid,
if (!IsSystemInitialized() || !pgss_qbuf[pgss->current_wbucket]) if (!IsSystemInitialized() || !pgss_qbuf[pgss->current_wbucket])
return; return;
bucket_id = get_next_wbucket(pgss); bucketid = get_next_wbucket(pgss);
if (bucket_id != pgss->current_wbucket) if (bucketid != pgss->current_wbucket)
{ {
reset = true; reset = true;
pgss->current_wbucket = bucket_id; pgss->current_wbucket = bucketid;
} }
update_planinfo(plan_info, kind, total_time, (uint64)GetUserId(), (uint64)MyDatabaseId, queryid, (uint64)pg_get_client_addr());
LWLockAcquire(pgss->lock, LW_EXCLUSIVE); LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
entry = pgss_get_entry(bucket_id, GetUserId(), MyDatabaseId, queryid, pg_get_client_addr(), &found);
switch (kind)
{
case PGSS_PARSE:
case PGSS_PLAN:
{
pgssQueryEntry *query_entry;
query_entry = pgss_store_query_info(bucketid, queryid, dbid, userid, ip, query, strlen(query), kind);
if (query_entry == NULL)
elog(DEBUG1, "pg_stat_monitor: out of memory");
break;
}
case PGSS_EXEC:
{
pgssQueryEntry *query_entry;
query_entry = pgss_store_query_info(bucketid, queryid, dbid, userid, ip, query, strlen(query), kind);
if (query_entry == NULL)
{
elog(DEBUG1, "pg_stat_monitor: out of memory");
break;
}
entry = pgss_get_entry(bucketid, userid, dbid, queryid, ip, planid);
if (entry == NULL) if (entry == NULL)
{ {
LWLockRelease(pgss->lock); elog(DEBUG1, "pg_stat_monitor: out of memory");
return; break;
} }
/* In case query is not found in the hash, add that into hash. */ if (jstate == NULL)
if (!found)
store_query(bucket_id, queryid, query, strlen(query));
if (jstate == NULL && kind == PGSS_EXEC)
pgss_update_entry(entry, /* entry */ pgss_update_entry(entry, /* entry */
bucket_id, /* bucketid */ bucketid, /* bucketid */
queryid, /* queryid */ queryid, /* queryid */
query, /* query */ query, /* query */
plan_info, /* PlanInfo */ plan_info, /* PlanInfo */
@ -1279,7 +1240,18 @@ pgss_store(uint64 queryid,
rows, /* rows */ rows, /* rows */
bufusage, /* bufusage */ bufusage, /* bufusage */
walusage, /* walusage */ walusage, /* walusage */
reset); /* reset */ reset, /* reset */
kind); /* kind */
}
break;
case PGSS_FINISHED:
case PGSS_NUMKIND:
case PGSS_INVALID:
break;
case PGSS_ERROR:
break;
}
LWLockRelease(pgss->lock); LWLockRelease(pgss->lock);
} }
/* /*
@ -1296,6 +1268,7 @@ pg_stat_monitor_reset(PG_FUNCTION_ARGS)
errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries"))); errmsg("pg_stat_monitor: must be loaded via shared_preload_libraries")));
LWLockAcquire(pgss->lock, LW_EXCLUSIVE); LWLockAcquire(pgss->lock, LW_EXCLUSIVE);
hash_entry_dealloc(-1); hash_entry_dealloc(-1);
hash_query_entry_dealloc(-1);
LWLockRelease(pgss->lock); LWLockRelease(pgss->lock);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
@ -1307,6 +1280,25 @@ pg_stat_monitor(PG_FUNCTION_ARGS)
return (Datum) 0; return (Datum) 0;
} }
static bool
IsBucketValid(uint64 bucketid)
{
struct tm tm;
time_t bucket_t,current_t;
double diff_t;
pgssSharedState *pgss = pgsm_get_ss();
memset(&tm, 0, sizeof(tm));
strptime(pgss->bucket_start_time[bucketid], "%Y-%m-%d %H:%M:%S", &tm);
bucket_t = mktime(&tm);
time(&current_t);
diff_t = difftime(current_t, bucket_t);
if (diff_t > (PGSM_BUCKET_TIME * PGSM_MAX_BUCKETS))
return false;
return true;
}
/* Common code for all versions of pg_stat_statements() */ /* Common code for all versions of pg_stat_statements() */
static void static void
pg_stat_monitor_internal(FunctionCallInfo fcinfo, pg_stat_monitor_internal(FunctionCallInfo fcinfo,
@ -1317,21 +1309,12 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
Tuplestorestate *tupstore; Tuplestorestate *tupstore;
MemoryContext per_query_ctx; MemoryContext per_query_ctx;
MemoryContext oldcontext; MemoryContext oldcontext;
Oid userid = GetUserId();
bool is_allowed_role;
HASH_SEQ_STATUS hash_seq; HASH_SEQ_STATUS hash_seq;
pgssEntry *entry; pgssEntry *entry;
char *query_txt;
char queryid_txt[64];
char planid_txt[64];
char parentid_txt[64]; char parentid_txt[64];
pgssSharedState *pgss = pgsm_get_ss(); pgssSharedState *pgss = pgsm_get_ss();
HTAB *pgss_hash = pgsm_get_hash(); HTAB *pgss_hash = pgsm_get_hash();
char *query_txt = (char*) malloc(PGSM_QUERY_MAX_LEN);
query_txt = (char*) malloc(PGSM_QUERY_MAX_LEN);
/* Superusers or members of pg_read_all_stats members are allowed */
is_allowed_role = is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS);
/* Safety check... */ /* Safety check... */
if (!IsSystemInitialized()) if (!IsSystemInitialized())
@ -1358,7 +1341,7 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "pg_stat_monitor: return type must be a row type"); elog(ERROR, "pg_stat_monitor: return type must be a row type");
if (tupdesc->natts != 46) if (tupdesc->natts != 48)
elog(ERROR, "pg_stat_monitor: incorrect number of output arguments, required %d", tupdesc->natts); elog(ERROR, "pg_stat_monitor: incorrect number of output arguments, required %d", tupdesc->natts);
tupstore = tuplestore_begin_heap(true, false, work_mem); tupstore = tuplestore_begin_heap(true, false, work_mem);
@ -1373,83 +1356,37 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
hash_seq_init(&hash_seq, pgss_hash); hash_seq_init(&hash_seq, pgss_hash);
while ((entry = hash_seq_search(&hash_seq)) != NULL) while ((entry = hash_seq_search(&hash_seq)) != NULL)
{ {
Datum values[PG_STAT_STATEMENTS_COLS]; Datum values[PG_STAT_STATEMENTS_COLS] = {0};
bool nulls[PG_STAT_STATEMENTS_COLS]; bool nulls[PG_STAT_STATEMENTS_COLS] = {0};
int i = 0; int i = 0;
Counters tmp; Counters tmp;
double stddev; double stddev;
char queryid_text[16] = {0};
char planid_text[16] = {0};
uint64 queryid = entry->key.queryid; uint64 queryid = entry->key.queryid;
struct tm tm; uint64 bucketid = entry->key.bucket_id;
time_t bucket_t,current_t; uint64 dbid = entry->key.dbid;
double diff_t; uint64 userid = entry->key.userid;
char str[64]; uint64 ip = entry->key.ip;
uint64 query_hash; uint64 planid = entry->key.planid;
PlanInfo plan_info;
memset(&plan_info, 0, sizeof(plan_info)); unsigned char *buf = pgss_qbuf[bucketid];
snprintf(str, 64, "%08lx%08lX%08lX%08lX", (uint64)entry->key.userid, (uint64)entry->key.dbid, queryid, (uint64)entry->key.ip); char *query_txt = (char*) malloc(PGSM_QUERY_MAX_LEN);
query_hash = DatumGetUInt64(hash_any_extended((const unsigned char*)str, strlen(str), 0)); bool is_allowed_role = is_member_of_role(GetUserId(), DEFAULT_ROLE_READ_ALL_STATS);
pgss_get_plan(query_hash, &plan_info);
memset(&tm, 0, sizeof(tm)); if (!IsBucketValid(bucketid))
strptime(pgss->bucket_start_time[entry->key.bucket_id], "%Y-%m-%d %H:%M:%S", &tm);
bucket_t = mktime(&tm);
time(&current_t);
diff_t = difftime(current_t, bucket_t);
if (diff_t > (PGSM_BUCKET_TIME * PGSM_MAX_BUCKETS))
continue; continue;
memset(values, 0, sizeof(values)); if (!hash_find_query_entry(bucketid, queryid, dbid, userid, ip))
memset(nulls, 0, sizeof(nulls)); continue;
if (!hash_find_query_entry(entry->key.bucket_id, queryid)) if (read_query(buf, bucketid, queryid, query_txt) == 0)
{ {
sprintf(query_txt, "%s", "pg_stat_monitor: queryid not found in hash and in temporay file"); int len;
} len = read_query_buffer(bucketid, queryid, query_txt);
else
{
int len = 0;
unsigned char *buf = pgss_qbuf[entry->key.bucket_id];
if(read_query(buf, queryid, query_txt) == 0)
{
switch(PGSM_OVERFLOW_TARGET)
{
case OVERFLOW_TARGET_NONE:
sprintf(query_txt, "%s", "query not found in query shared_buffer, no space left");
break;
case OVERFLOW_TARGET_DISK:
{
len = read_query_buffer(entry->key.bucket_id, queryid, query_txt);
if (len != MAX_QUERY_BUFFER_BUCKET) if (len != MAX_QUERY_BUFFER_BUCKET)
sprintf(query_txt, "%s", "query not found either in hash nor in temporay file"); sprintf(query_txt, "%s", "<insufficient disk/shared space>");
} }
break;
}
}
}
if (query_txt)
sprintf(queryid_txt, "%08lX", queryid);
else
sprintf(queryid_txt, "%08lX", (long unsigned int)0);
sprintf(planid_txt, "%08lX", plan_info.planid);
/* bucketid at column number 0 */
values[i++] = ObjectIdGetDatum(entry->key.bucket_id);
/* userid at column number 1 */
values[i++] = ObjectIdGetDatum(entry->key.userid);
/* dbid at column number 2 */
values[i++] = ObjectIdGetDatum(entry->key.dbid);
/* ip address at column number 3 */
/* Superusers or members of pg_read_all_stats members are allowed */
if (is_allowed_role || entry->key.userid == userid)
values[i++] = Int64GetDatumFast(entry->key.ip);
else
values[i++] = Int64GetDatumFast(0);
/* copy counters to a local variable to keep locking time short */ /* copy counters to a local variable to keep locking time short */
{ {
@ -1458,17 +1395,76 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
tmp = e->counters; tmp = e->counters;
SpinLockRelease(&e->mutex); SpinLockRelease(&e->mutex);
} }
/* bucketid at column number 0 */
values[i++] = Int64GetDatumFast(bucketid);
/* queryid at column number 4 */ /* userid at column number 1 */
values[i++] = CStringGetTextDatum(queryid_txt); values[i++] = ObjectIdGetDatum(userid);
/* planid at column number 5 */ /* dbid at column number 2 */
if (plan_info.planid != 0) values[i++] = ObjectIdGetDatum(dbid);
values[i++] = CStringGetTextDatum(planid_txt);
/*
* ip address at column number 3,
* Superusers or members of pg_read_all_stats members
* are allowed
*/
if (is_allowed_role || userid == GetUserId())
values[i++] = Int64GetDatumFast(ip);
else else
nulls[i++] = true; nulls[i++] = true;
/* parentid at column number 6 */ /* queryid at column number 4 */
sprintf(queryid_text, "%08lX", queryid);
values[i++] = CStringGetTextDatum(queryid_text);
/* planid at column number 5 */
if (planid)
{
sprintf(planid_text, "%08lX", planid);
values[i++] = CStringGetTextDatum(planid_text);
}
else
{
nulls[i++] = true;
}
if (is_allowed_role || userid == GetUserId())
{
if (showtext)
{
char *enc;
/* query at column number 6 */
enc = pg_any_to_server(query_txt, strlen(query_txt), GetDatabaseEncoding());
values[i++] = CStringGetTextDatum(enc);
if (enc != query_txt)
pfree(enc);
/* plan at column number 7 */
if (planid && tmp.planinfo.plan_text)
values[i++] = CStringGetTextDatum(tmp.planinfo.plan_text);
else
nulls[i++] = true;
}
else
{
/* query at column number 6 */
nulls[i++] = true;
/* plan at column number 7 */
nulls[i++] = true;
}
}
else
{
/* query text at column number 6 */
values[i++] = CStringGetTextDatum("<insufficient privilege>");
values[i++] = CStringGetTextDatum("<insufficient privilege>");
}
/* state at column number 8 */
values[i++] = Int64GetDatumFast(tmp.state);
/* parentid at column number 9 */
if (tmp.info.parentid != UINT64CONST(0)) if (tmp.info.parentid != UINT64CONST(0))
{ {
sprintf(parentid_txt,"%08lX",tmp.info.parentid); sprintf(parentid_txt,"%08lX",tmp.info.parentid);
@ -1479,53 +1475,11 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
nulls[i++] = true; nulls[i++] = true;
} }
if (is_allowed_role || entry->key.userid == userid)
{
/* query at column number 7 */
/* plan at column number 8 */
if (showtext)
{
if (query_txt)
{
char *enc;
enc = pg_any_to_server(query_txt, strlen(query_txt), entry->encoding);
values[i++] = CStringGetTextDatum(enc);
values[i++] = CStringGetTextDatum(plan_info.plan_text);
if (enc != query_txt)
pfree(enc);
}
else
{
nulls[i++] = true;
nulls[i++] = true;
}
}
else
{
/* Query text not requested */
nulls[i++] = true;
nulls[i++] = true;
}
}
else
{
/*
* Don't show query text, but hint as to the reason for not doing
* so if it was requested
*/
if (showtext)
values[i++] = CStringGetTextDatum("<insufficient privilege>");
else
nulls[i++] = true;
/* skip plan_text */
nulls[i++] = true;
}
/* application_name at column number 9 */ /* application_name at column number 9 */
if (strlen(tmp.info.application_name) == 0) if (strlen(tmp.info.application_name) > 0)
nulls[i++] = true;
else
values[i++] = CStringGetTextDatum(tmp.info.application_name); values[i++] = CStringGetTextDatum(tmp.info.application_name);
else
nulls[i++] = true;
/* relations at column number 10 */ /* relations at column number 10 */
if (tmp.info.num_relations > 0) if (tmp.info.num_relations > 0)
@ -1608,22 +1562,36 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
/* calls at column number 22 */ /* calls at column number 22 */
values[i++] = Int64GetDatumFast(tmp.calls.rows); values[i++] = Int64GetDatumFast(tmp.calls.rows);
/* plan_calls at column number 23 */ if (tmp.calls.calls == 0)
values[i++] = Int64GetDatumFast(plan_info.plans); {
/* Query of pg_stat_monitor itslef started from zero count */
tmp.calls.calls++;
tmp.resp_calls[0]++;
}
/* plan_total_time at column number 24 */ /* calls at column number 23 */
values[i++] = Float8GetDatumFast(plan_info.time.total_time); values[i++] = Int64GetDatumFast(tmp.plancalls.calls);
/* plan_min_time at column number 25 */ /* total_time at column number 24 */
values[i++] = Float8GetDatumFast(plan_info.time.min_time); values[i++] = Float8GetDatumFast(tmp.plantime.total_time);
/* plan_max_time at column number 26 */ /* min_time at column number 25 */
values[i++] = Float8GetDatumFast(plan_info.time.max_time); values[i++] = Float8GetDatumFast(tmp.plantime.min_time);
/* plan_mean_time at column number 27 */ /* max_time at column number 26 */
values[i++] = Float8GetDatumFast(plan_info.time.mean_time); values[i++] = Float8GetDatumFast(tmp.plantime.max_time);
/* blocks are from column number 28 - 39 */ /* mean_time at column number 27 */
values[i++] = Float8GetDatumFast(tmp.plantime.mean_time);
if (tmp.plancalls.calls > 1)
stddev = sqrt(tmp.plantime.sum_var_time / tmp.plancalls.calls);
else
stddev = 0.0;
/* calls at column number 28 */
values[i++] = Float8GetDatumFast(stddev);
/* blocks are from column number 29 - 40 */
values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_hit); values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_hit);
values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_read); values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_read);
values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_dirtied); values[i++] = Int64GetDatumFast(tmp.blocks.shared_blks_dirtied);
@ -1637,22 +1605,22 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
values[i++] = Float8GetDatumFast(tmp.blocks.blk_read_time); values[i++] = Float8GetDatumFast(tmp.blocks.blk_read_time);
values[i++] = Float8GetDatumFast(tmp.blocks.blk_write_time); values[i++] = Float8GetDatumFast(tmp.blocks.blk_write_time);
/* resp_calls at column number 40 */ /* resp_calls at column number 41 */
values[i++] = IntArrayGetTextDatum(tmp.resp_calls, MAX_RESPONSE_BUCKET); values[i++] = IntArrayGetTextDatum(tmp.resp_calls, MAX_RESPONSE_BUCKET);
/* utime at column number 41 */ /* utime at column number 42 */
values[i++] = Float8GetDatumFast(tmp.sysinfo.utime); values[i++] = Float8GetDatumFast(tmp.sysinfo.utime);
/* stime at column number 42 */ /* stime at column number 43 */
values[i++] = Float8GetDatumFast(tmp.sysinfo.stime); values[i++] = Float8GetDatumFast(tmp.sysinfo.stime);
{ {
char buf[256]; char buf[256];
Datum wal_bytes; Datum wal_bytes;
/* wal_records at column number 43 */ /* wal_records at column number 44 */
values[i++] = Int64GetDatumFast(tmp.walusage.wal_records); values[i++] = Int64GetDatumFast(tmp.walusage.wal_records);
/* wal_fpi at column number 44 */ /* wal_fpi at column number 45 */
values[i++] = Int64GetDatumFast(tmp.walusage.wal_fpi); values[i++] = Int64GetDatumFast(tmp.walusage.wal_fpi);
snprintf(buf, sizeof buf, UINT64_FORMAT, tmp.walusage.wal_bytes); snprintf(buf, sizeof buf, UINT64_FORMAT, tmp.walusage.wal_bytes);
@ -1662,13 +1630,12 @@ pg_stat_monitor_internal(FunctionCallInfo fcinfo,
CStringGetDatum(buf), CStringGetDatum(buf),
ObjectIdGetDatum(0), ObjectIdGetDatum(0),
Int32GetDatum(-1)); Int32GetDatum(-1));
/* wal_bytes at column number 45 */ /* wal_bytes at column number 46 */
values[i++] = wal_bytes; values[i++] = wal_bytes;
} }
tuplestore_putvalues(tupstore, tupdesc, values, nulls); tuplestore_putvalues(tupstore, tupdesc, values, nulls);
} }
free(query_txt); free(query_txt);
/* clean up and return the tuplestore */ /* clean up and return the tuplestore */
LWLockRelease(pgss->lock); LWLockRelease(pgss->lock);
@ -2651,7 +2618,7 @@ intarray_get_datum(int32 arr[], int len)
} }
static uint64 static uint64
read_query(unsigned char *buf, uint64 queryid, char * query) read_query(unsigned char *buf, uint64 bucketid, uint64 queryid, char * query)
{ {
bool found = false; bool found = false;
uint64 query_id = 0; uint64 query_id = 0;
@ -2661,13 +2628,13 @@ read_query(unsigned char *buf, uint64 queryid, char * query)
memcpy(&buf_len, buf, sizeof (uint64)); memcpy(&buf_len, buf, sizeof (uint64));
if (buf_len <= 0) if (buf_len <= 0)
return 0; goto exit;
rlen = sizeof (uint64); /* Move forwad to skip length bytes */ rlen = sizeof (uint64); /* Move forwad to skip length bytes */
for(;;) for(;;)
{ {
if (rlen >= buf_len) if (rlen >= buf_len)
return 0; goto exit;
memcpy(&query_id, &buf[rlen], sizeof (uint64)); /* query id */ memcpy(&query_id, &buf[rlen], sizeof (uint64)); /* query id */
if (query_id == queryid) if (query_id == queryid)
@ -2680,7 +2647,7 @@ read_query(unsigned char *buf, uint64 queryid, char * query)
memcpy(&query_len, &buf[rlen], sizeof (uint64)); /* query len */ memcpy(&query_len, &buf[rlen], sizeof (uint64)); /* query len */
rlen += sizeof (uint64); rlen += sizeof (uint64);
if (buf_len < rlen + query_len) if (buf_len < rlen + query_len)
return 0; goto exit;
if (found) if (found)
{ {
@ -2693,15 +2660,29 @@ read_query(unsigned char *buf, uint64 queryid, char * query)
} }
rlen += query_len; rlen += query_len;
} }
exit:
if (PGSM_OVERFLOW_TARGET == OVERFLOW_TARGET_NONE)
{
sprintf(query, "%s", "<insufficient shared space>");
return -1;
}
return 0; return 0;
} }
static void static pgssQueryEntry*
store_query(int bucket_id, uint64 queryid, const char *query, uint64 query_len) pgss_store_query_info(uint64 bucketid,
uint64 queryid,
uint64 dbid,
uint64 userid,
uint64 ip,
const char *query,
uint64 query_len,
pgssStoreKind kind)
{ {
uint64 buf_len = 0; uint64 buf_len = 0;
pgssSharedState *pgss = pgsm_get_ss(); pgssSharedState *pgss = pgsm_get_ss();
unsigned char *buf = pgss_qbuf[pgss->current_wbucket]; unsigned char *buf = pgss_qbuf[pgss->current_wbucket];
pgssQueryEntry *entry;
if (query_len > PGSM_QUERY_MAX_LEN) if (query_len > PGSM_QUERY_MAX_LEN)
query_len = PGSM_QUERY_MAX_LEN; query_len = PGSM_QUERY_MAX_LEN;
@ -2709,12 +2690,15 @@ store_query(int bucket_id, uint64 queryid, const char *query, uint64 query_len)
/* Already have query in the shared buffer, there /* Already have query in the shared buffer, there
* is no need to add that again. * is no need to add that again.
*/ */
if (hash_find_query_entry(bucket_id, queryid)) entry = hash_find_query_entry(bucketid, queryid, dbid, userid, ip);
return; if (entry)
return entry;
if (!hash_create_query_entry(bucket_id, queryid)) entry = hash_create_query_entry(bucketid, queryid, dbid, userid, ip);
return; if (!entry)
return NULL;
entry->state = kind;
memcpy(&buf_len, buf, sizeof (uint64)); memcpy(&buf_len, buf, sizeof (uint64));
if (buf_len == 0) if (buf_len == 0)
buf_len += sizeof (uint64); buf_len += sizeof (uint64);
@ -2724,10 +2708,10 @@ store_query(int bucket_id, uint64 queryid, const char *query, uint64 query_len)
switch(PGSM_OVERFLOW_TARGET) switch(PGSM_OVERFLOW_TARGET)
{ {
case OVERFLOW_TARGET_NONE: case OVERFLOW_TARGET_NONE:
return; return NULL;
case OVERFLOW_TARGET_DISK: case OVERFLOW_TARGET_DISK:
{ {
dump_queries_buffer(bucket_id, buf, MAX_QUERY_BUFFER_BUCKET); dump_queries_buffer(bucketid, buf, MAX_QUERY_BUFFER_BUCKET);
buf_len = sizeof (uint64); buf_len = sizeof (uint64);
} }
break; break;
@ -2745,6 +2729,7 @@ store_query(int bucket_id, uint64 queryid, const char *query, uint64 query_len)
memcpy(&buf[buf_len], query, query_len); /* query */ memcpy(&buf[buf_len], query, query_len); /* query */
buf_len += query_len; buf_len += query_len;
memcpy(buf, &buf_len, sizeof (uint64)); memcpy(buf, &buf_len, sizeof (uint64));
return entry;
} }
static uint64 static uint64
@ -2915,7 +2900,7 @@ read_query_buffer(int bucket_id, uint64 queryid, char *query_txt)
break; break;
} }
off += buf_len; off += buf_len;
if (read_query(buf, queryid, query_txt)) if (read_query(buf, bucket_id, queryid, query_txt))
break; break;
} }
if (fd > 0) if (fd > 0)

View File

@ -127,8 +127,11 @@ typedef enum pgssStoreKind
* reference the underlying values in the arrays in the Counters struct, * reference the underlying values in the arrays in the Counters struct,
* and this order is required in pg_stat_statements_internal(). * and this order is required in pg_stat_statements_internal().
*/ */
PGSS_PLAN = 0, PGSS_PARSE = 0,
PGSS_PLAN,
PGSS_EXEC, PGSS_EXEC,
PGSS_ERROR,
PGSS_FINISHED,
PGSS_NUMKIND /* Must be last value of this enum */ PGSS_NUMKIND /* Must be last value of this enum */
} pgssStoreKind; } pgssStoreKind;
@ -160,37 +163,26 @@ typedef struct CallTime
typedef struct pgssQueryHashKey typedef struct pgssQueryHashKey
{ {
uint64 queryid; /* query identifier */
uint64 bucket_id; /* bucket number */ uint64 bucket_id; /* bucket number */
uint64 queryid; /* query identifier */
uint64 userid; /* user OID */
uint64 dbid; /* database OID */
uint64 ip; /* client ip address */
} pgssQueryHashKey; } pgssQueryHashKey;
typedef struct pgssQueryEntry typedef struct pgssQueryEntry
{ {
pgssQueryHashKey key; /* hash key of entry - MUST BE FIRST */ pgssQueryHashKey key; /* hash key of entry - MUST BE FIRST */
uint64 pos; /* bucket number */ uint64 pos; /* bucket number */
uint64 state; /* query state */
} pgssQueryEntry; } pgssQueryEntry;
typedef struct PlanInfo typedef struct PlanInfo
{ {
uint64 planid; /* plan identifier */ uint64 planid; /* plan identifier */
uint64 plans; /* how many times plan */
CallTime time;
char plan_text[PLAN_TEXT_LEN]; /* plan text */ char plan_text[PLAN_TEXT_LEN]; /* plan text */
} PlanInfo; } PlanInfo;
/* shared nenory storage for the query */
typedef struct pgssPlanHashKey
{
uint64 query_hash; /* query reference identifier */
} pgssPlanHashKey;
typedef struct pgssPlanEntry
{
pgssPlanHashKey key; /* hash key of entry - MUST BE FIRST */
PlanInfo plan_info; /* planning information */
slock_t mutex; /* protects the counters only */
} pgssPlanEntry;
typedef struct pgssHashKey typedef struct pgssHashKey
{ {
uint64 bucket_id; /* bucket number */ uint64 bucket_id; /* bucket number */
@ -198,6 +190,7 @@ typedef struct pgssHashKey
uint64 userid; /* user OID */ uint64 userid; /* user OID */
uint64 dbid; /* database OID */ uint64 dbid; /* database OID */
uint64 ip; /* client ip address */ uint64 ip; /* client ip address */
uint64 planid; /* plan identifier */
} pgssHashKey; } pgssHashKey;
typedef struct QueryInfo typedef struct QueryInfo
@ -263,14 +256,18 @@ typedef struct Counters
uint64 bucket_id; /* bucket id */ uint64 bucket_id; /* bucket id */
Calls calls; Calls calls;
QueryInfo info; QueryInfo info;
PlanInfo plan_info;
CallTime time; CallTime time;
Calls plancalls;
CallTime plantime;
PlanInfo planinfo;
Blocks blocks; Blocks blocks;
SysInfo sysinfo; SysInfo sysinfo;
ErrorInfo error; ErrorInfo error;
Wal_Usage walusage; Wal_Usage walusage;
int plans;
int resp_calls[MAX_RESPONSE_BUCKET]; /* execution time's in msec */ int resp_calls[MAX_RESPONSE_BUCKET]; /* execution time's in msec */
uint64 state; /* query state */
} Counters; } Counters;
/* Some global structure to get the cpu usage, really don't like the idea of global variable */ /* Some global structure to get the cpu usage, really don't like the idea of global variable */
@ -362,18 +359,18 @@ void pgss_shmem_shutdown(int code, Datum arg);
int pgsm_get_bucket_size(void); int pgsm_get_bucket_size(void);
pgssSharedState* pgsm_get_ss(void); pgssSharedState* pgsm_get_ss(void);
HTAB *pgsm_get_plan_hash(void); HTAB *pgsm_get_plan_hash(void);
HTAB *pgsm_get_query_hash(void);
HTAB *pgsm_get_hash(void); HTAB *pgsm_get_hash(void);
HTAB *pgsm_get_plan_hash(void); HTAB *pgsm_get_plan_hash(void);
HTAB* pgsm_get_query_hash(void); HTAB* pgsm_get_query_hash(void);
void hash_entry_reset(void); void hash_entry_reset(void);
void hash_query_entry_dealloc(int bucket); void hash_query_entry_dealloc(int bucket);
void hash_entry_dealloc(int bucket); void hash_entry_dealloc(int bucket);
pgssPlanEntry *hash_plan_entry_alloc(pgssSharedState *pgss, pgssPlanHashKey *key);
pgssEntry* hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding); pgssEntry* hash_entry_alloc(pgssSharedState *pgss, pgssHashKey *key, int encoding);
Size hash_memsize(void); Size hash_memsize(void);
bool hash_find_query_entry(uint64 bucket_id, uint64 queryid); pgssQueryEntry* hash_find_query_entry(uint64 bucket_id, uint64 queryid, uint64 dbid, uint64 userid, uint64 ip);
bool hash_create_query_entry(uint64 bucket_id, uint64 queryid); pgssQueryEntry* hash_create_query_entry(uint64 bucket_id, uint64 queryid, uint64 dbid, uint64 userid, uint64 ip);
void pgss_startup(void); void pgss_startup(void);
void set_qbuf(int i, unsigned char *); void set_qbuf(int i, unsigned char *);

View File

@ -13,11 +13,10 @@ SELECT 1 AS num;
SELECT query,application_name FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query,application_name FROM pg_stat_monitor ORDER BY query COLLATE "C";
query | application_name query | application_name
--------------------------------------------------------------------------------+----------------------------- ---------------------------------+-----------------------------
SELECT $1 AS num | pg_regress/application_name SELECT $1 AS num | pg_regress/application_name
SELECT pg_stat_monitor_reset(); | pg_regress/application_name SELECT pg_stat_monitor_reset(); | pg_regress/application_name
SELECT query,application_name FROM pg_stat_monitor ORDER BY query COLLATE "C"; | (2 rows)
(3 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -5,12 +5,6 @@ SELECT pg_stat_monitor_reset();
(1 row) (1 row)
select pg_sleep(.5);
pg_sleep
----------
(1 row)
SELECT 1 AS num; SELECT 1 AS num;
num num
----- -----
@ -19,12 +13,10 @@ SELECT 1 AS num;
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C";
query query
--------------------------------------------------------------- ---------------------------------
SELECT $1 AS num SELECT $1 AS num
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C"; (2 rows)
select pg_sleep($1)
(4 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -6,6 +6,7 @@ SELECT pg_stat_monitor_reset();
(1 row) (1 row)
CREATE TABLE t1 (a INTEGER); CREATE TABLE t1 (a INTEGER);
CREATE TABLE t2 (b INTEGER);
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
SELECT a FROM t1; SELECT a FROM t1;
a a
@ -15,8 +16,8 @@ SELECT a FROM t1;
UPDATE t1 SET a = 2; UPDATE t1 SET a = 2;
DELETE FROM t1; DELETE FROM t1;
SELECT a FROM t1 FOR UPDATE; SELECT b FROM t2 FOR UPDATE;
a b
--- ---
(0 rows) (0 rows)
@ -24,17 +25,18 @@ TRUNCATE t1;
DROP TABLE t1; DROP TABLE t1;
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C";
query | cmd_type | cmd_type_text query | cmd_type | cmd_type_text
-----------------------------------------------------------------------------------------+----------+--------------- ---------------------------------+----------+---------------
CREATE TABLE t1 (a INTEGER); | 0 | CREATE TABLE t1 (a INTEGER); | 0 |
CREATE TABLE t2 (b INTEGER); | 0 |
DELETE FROM t1; | 4 | DELETE DELETE FROM t1; | 4 | DELETE
DROP TABLE t1; | 0 | DROP TABLE t1; | 0 |
INSERT INTO t1 VALUES($1) | 3 | INSERT INSERT INTO t1 VALUES($1) | 3 | INSERT
SELECT a FROM t1; | 1 | SELECT SELECT a FROM t1; | 1 | SELECT
SELECT b FROM t2 FOR UPDATE; | 1 | SELECT
SELECT pg_stat_monitor_reset(); | 1 | SELECT SELECT pg_stat_monitor_reset(); | 1 | SELECT
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0 |
TRUNCATE t1; | 0 | TRUNCATE t1; | 0 |
UPDATE t1 SET a = $1 | 2 | UPDATE UPDATE t1 SET a = $1 | 2 | UPDATE
(9 rows) (10 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -1,4 +1,10 @@
CREATE EXTENSION pg_stat_monitor; CREATE EXTENSION pg_stat_monitor;
SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset
-----------------------
(1 row)
CREATE TABLE t1 (a INTEGER); CREATE TABLE t1 (a INTEGER);
CREATE TABLE t2 (b INTEGER); CREATE TABLE t2 (b INTEGER);
CREATE TABLE t3 (c INTEGER); CREATE TABLE t3 (c INTEGER);
@ -34,8 +40,7 @@ SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C";
----------------------------------------------------------------------------------+------- ----------------------------------------------------------------------------------+-------
SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a; | 4 SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a; | 4
SELECT pg_stat_monitor_reset(); | 1 SELECT pg_stat_monitor_reset(); | 1
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 1 (2 rows)
(3 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset
@ -62,12 +67,8 @@ end $$;
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C";
query | calls query | calls
---------------------------------------------------------------------------------------------------+------- ---------------------------------------------------------------------------------------------------+-------
SELECT $1 AS num | 1
SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a; | 1000 SELECT a,b,c,d FROM t1, t2, t3, t4 WHERE t1.a = t2.b AND t3.c = t4.d ORDER BY a; | 1000
SELECT n + $3 | 1
SELECT n = $3 | 1
SELECT pg_stat_monitor_reset(); | 1 SELECT pg_stat_monitor_reset(); | 1
SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 1
do $$ +| 1 do $$ +| 1
declare +| declare +|
n integer:= 1; +| n integer:= 1; +|
@ -78,7 +79,7 @@ SELECT query,calls FROM pg_stat_monitor ORDER BY query COLLATE "C";
n := n + 1; +| n := n + 1; +|
end loop; +| end loop; +|
end $$; | end $$; |
(7 rows) (3 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -29,12 +29,11 @@ SELECT * FROM t3,t4 WHERE t3.c = t4.d;
\c contrib_regression \c contrib_regression
SELECT datname, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT datname, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
datname | query datname | query
--------------------+------------------------------------------------------------------------ --------------------+----------------------------------------
db1 | SELECT * FROM t1,t2 WHERE t1.a = t2.b; db1 | SELECT * FROM t1,t2 WHERE t1.a = t2.b;
db2 | SELECT * FROM t3,t4 WHERE t3.c = t4.d; db2 | SELECT * FROM t3,t4 WHERE t3.c = t4.d;
contrib_regression | SELECT datname, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
contrib_regression | SELECT pg_stat_monitor_reset(); contrib_regression | SELECT pg_stat_monitor_reset();
(4 rows) (3 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -22,18 +22,16 @@ END $$;
WARNING: warning message WARNING: warning message
SELECT query, elevel,sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query, elevel,sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C";
query | elevel | sqlcode | message query | elevel | sqlcode | message
----------------------------------------------------------------------------------------+--------+---------+----------------------------------- ----------------------------------+--------+---------+-----------------------------------
ELECET * FROM unknown; | 20 | 42601 | syntax error at or near "ELECET" ELECET * FROM unknown; | 20 | 42601 | syntax error at or near "ELECET"
SELECT $1/$2 | 0 | |
SELECT * FROM unknown; | 20 | 42P01 | relation "unknown" does not exist SELECT * FROM unknown; | 20 | 42P01 | relation "unknown" does not exist
SELECT 1/0; | 20 | 22012 | division by zero SELECT 1/0; | 20 | 22012 | division by zero
SELECT pg_stat_monitor_reset(); | 0 | | SELECT pg_stat_monitor_reset(); | 0 | |
SELECT query, elevel,sqlcode, message FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0 | |
do $$ +| 19 | 01000 | warning message do $$ +| 19 | 01000 | warning message
BEGIN +| | | BEGIN +| | |
RAISE WARNING 'warning message'; +| | | RAISE WARNING 'warning message';+| | |
END $$; | | | END $$; | | |
(7 rows) (5 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -38,14 +38,13 @@ SELECT * FROM foo1, foo2, foo3, foo4;
SELECT query, relations from pg_stat_monitor ORDER BY query; SELECT query, relations from pg_stat_monitor ORDER BY query;
query | relations query | relations
--------------------------------------------------------------+--------------------------------------------------- ---------------------------------------+---------------------------------------------------
SELECT * FROM foo1, foo2, foo3, foo4; | {public.foo1,public.foo2,public.foo3,public.foo4} SELECT * FROM foo1, foo2, foo3, foo4; | {public.foo1,public.foo2,public.foo3,public.foo4}
SELECT * FROM foo1, foo2, foo3; | {public.foo1,public.foo2,public.foo3} SELECT * FROM foo1, foo2, foo3; | {public.foo1,public.foo2,public.foo3}
SELECT * FROM foo1, foo2; | {public.foo1,public.foo2} SELECT * FROM foo1, foo2; | {public.foo1,public.foo2}
SELECT * FROM foo1; | {public.foo1} SELECT * FROM foo1; | {public.foo1}
SELECT pg_stat_monitor_reset(); | SELECT pg_stat_monitor_reset(); |
SELECT query, relations from pg_stat_monitor ORDER BY query; | (5 rows)
(6 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset
@ -90,14 +89,13 @@ SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4;
SELECT query, relations from pg_stat_monitor ORDER BY query; SELECT query, relations from pg_stat_monitor ORDER BY query;
query | relations query | relations
--------------------------------------------------------------+------------------------------------------- -----------------------------------------------------------+-------------------------------------------
SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4; | {sch1.foo1,sch2.foo2,sch3.foo3,sch4.foo4} SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3, sch4.foo4; | {sch1.foo1,sch2.foo2,sch3.foo3,sch4.foo4}
SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3; | {sch1.foo1,sch2.foo2,sch3.foo3} SELECT * FROM sch1.foo1, sch2.foo2, sch3.foo3; | {sch1.foo1,sch2.foo2,sch3.foo3}
SELECT * FROM sch1.foo1, sch2.foo2; | {sch1.foo1,sch2.foo2} SELECT * FROM sch1.foo1, sch2.foo2; | {sch1.foo1,sch2.foo2}
SELECT * FROM sch1.foo1; | {sch1.foo1} SELECT * FROM sch1.foo1; | {sch1.foo1}
SELECT pg_stat_monitor_reset(); | SELECT pg_stat_monitor_reset(); |
SELECT query, relations from pg_stat_monitor ORDER BY query; | (5 rows)
(6 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset
@ -123,12 +121,11 @@ SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2;
SELECT query, relations from pg_stat_monitor ORDER BY query; SELECT query, relations from pg_stat_monitor ORDER BY query;
query | relations query | relations
--------------------------------------------------------------+----------------------------------------------- -------------------------------------------------+-----------------------------------------------
SELECT * FROM sch1.foo1, foo1; | {sch1.foo1,public.foo1} SELECT * FROM sch1.foo1, foo1; | {sch1.foo1,public.foo1}
SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2; | {sch1.foo1,sch2.foo2,public.foo1,public.foo2} SELECT * FROM sch1.foo1, sch2.foo2, foo1, foo2; | {sch1.foo1,sch2.foo2,public.foo1,public.foo2}
SELECT pg_stat_monitor_reset(); | SELECT pg_stat_monitor_reset(); |
SELECT query, relations from pg_stat_monitor ORDER BY query; | (3 rows)
(4 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset
@ -169,14 +166,13 @@ SELECT * FROM v1,v2,v3,v4;
SELECT query, relations from pg_stat_monitor ORDER BY query; SELECT query, relations from pg_stat_monitor ORDER BY query;
query | relations query | relations
--------------------------------------------------------------+----------------------------------------------------------------------------------------------- ---------------------------------+-----------------------------------------------------------------------------------------------
SELECT * FROM v1,v2,v3,v4; | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3,public.v4*,public.foo4} SELECT * FROM v1,v2,v3,v4; | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3,public.v4*,public.foo4}
SELECT * FROM v1,v2,v3; | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3} SELECT * FROM v1,v2,v3; | {public.v1*,public.foo1,public.v2*,public.foo2,public.v3*,public.foo3}
SELECT * FROM v1,v2; | {public.v1*,public.foo1,public.v2*,public.foo2} SELECT * FROM v1,v2; | {public.v1*,public.foo1,public.v2*,public.foo2}
SELECT * FROM v1; | {public.v1*,public.foo1} SELECT * FROM v1; | {public.v1*,public.foo1}
SELECT pg_stat_monitor_reset(); | SELECT pg_stat_monitor_reset(); |
SELECT query, relations from pg_stat_monitor ORDER BY query; | (5 rows)
(6 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -1,6 +1,7 @@
CREATE EXTENSION pg_stat_monitor; CREATE EXTENSION pg_stat_monitor;
CREATE TABLE t1(a int); CREATE TABLE t1(a int);
CREATE TABLE t2(b int); CREATE TABLE t2(b int);
ERROR: relation "t2" already exists
INSERT INTO t1 VALUES(generate_series(1,1000)); INSERT INTO t1 VALUES(generate_series(1,1000));
INSERT INTO t2 VALUES(generate_series(1,5000)); INSERT INTO t2 VALUES(generate_series(1,5000));
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
@ -8541,14 +8542,13 @@ SELECt * FROM t2 WHERE b % 2 = 0;
SELECT query, rows FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query, rows FROM pg_stat_monitor ORDER BY query COLLATE "C";
query | rows query | rows
---------------------------------------------------------------------+------ -------------------------------------+------
SELECT * FROM t1 LIMIT $1 | 10 SELECT * FROM t1 LIMIT $1 | 10
SELECT * FROM t1; | 1000 SELECT * FROM t1; | 1000
SELECT * FROM t2; | 5000 SELECT b FROM t2 FOR UPDATE; | 5000
SELECT pg_stat_monitor_reset(); | 1 SELECT pg_stat_monitor_reset(); | 1
SELECT query, rows FROM pg_stat_monitor ORDER BY query COLLATE "C"; | 0
SELECt * FROM t2 WHERE b % $1 = $2 | 2500 SELECt * FROM t2 WHERE b % $1 = $2 | 2500
(6 rows) (5 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -24,8 +24,8 @@ SELECT add2(1,2);
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
query | top_query query | top_query
--------------------------------------------------------------------------+-------------------- -------------------------------------------------------------+--------------------
CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS +| CREATE OR REPLACE FUNCTION add(int, int) RETURNS INTEGER AS+|
$$ +| $$ +|
BEGIN +| BEGIN +|
return (select $1 + $2); +| return (select $1 + $2); +|
@ -37,11 +37,9 @@ SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C";
END; +| END; +|
$$ language plpgsql; | $$ language plpgsql; |
SELECT (select $1 + $2) | SELECT add2($1,$2) SELECT (select $1 + $2) | SELECT add2($1,$2)
SELECT add($1,$2) |
SELECT add2($1,$2) | SELECT add2($1,$2) |
SELECT pg_stat_monitor_reset(); | SELECT pg_stat_monitor_reset(); |
SELECT query, top_query FROM pg_stat_monitor ORDER BY query COLLATE "C"; | (5 rows)
(7 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -28,17 +28,16 @@ SELECT * FROM t2;
SET ROLE su; SET ROLE su;
SELECT userid, query FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT userid, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
userid | query userid | query
--------+----------------------------------------------------------------------- --------+---------------------------------
u1 | CREATE TABLE t1 (a int); u1 | CREATE TABLE t1 (a int);
u2 | CREATE TABLE t2 (a int); u2 | CREATE TABLE t2 (a int);
u1 | SELECT * FROM t1; u1 | SELECT * FROM t1;
u2 | SELECT * FROM t2; u2 | SELECT * FROM t2;
su | SELECT pg_stat_monitor_reset(); su | SELECT pg_stat_monitor_reset();
su | SELECT userid, query FROM pg_stat_monitor ORDER BY query COLLATE "C";
su | SET ROLE su; su | SET ROLE su;
u1 | SET ROLE u1; u1 | SET ROLE u1;
u2 | SET ROLE u2; u2 | SET ROLE u2;
(9 rows) (8 rows)
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
pg_stat_monitor_reset pg_stat_monitor_reset

View File

@ -1,6 +1,5 @@
CREATE EXTENSION pg_stat_monitor; CREATE EXTENSION pg_stat_monitor;
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
select pg_sleep(.5);
SELECT 1 AS num; SELECT 1 AS num;
SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query FROM pg_stat_monitor ORDER BY query COLLATE "C";
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();

View File

@ -2,11 +2,12 @@ CREATE EXTENSION pg_stat_monitor;
SELECT pg_stat_monitor_reset(); SELECT pg_stat_monitor_reset();
CREATE TABLE t1 (a INTEGER); CREATE TABLE t1 (a INTEGER);
CREATE TABLE t2 (b INTEGER);
INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(1);
SELECT a FROM t1; SELECT a FROM t1;
UPDATE t1 SET a = 2; UPDATE t1 SET a = 2;
DELETE FROM t1; DELETE FROM t1;
SELECT a FROM t1 FOR UPDATE; SELECT b FROM t2 FOR UPDATE;
TRUNCATE t1; TRUNCATE t1;
DROP TABLE t1; DROP TABLE t1;
SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C"; SELECT query, cmd_type, cmd_type_text FROM pg_stat_monitor ORDER BY query COLLATE "C";

View File

@ -1,4 +1,5 @@
CREATE EXTENSION pg_stat_monitor; CREATE EXTENSION pg_stat_monitor;
SELECT pg_stat_monitor_reset();
CREATE TABLE t1 (a INTEGER); CREATE TABLE t1 (a INTEGER);
CREATE TABLE t2 (b INTEGER); CREATE TABLE t2 (b INTEGER);