4 * Definitions for the PostgreSQL statistics collector daemon.
6 * Copyright (c) 2001-2007, PostgreSQL Global Development Group
8 * $PostgreSQL: pgsql/src/include/pgstat.h,v 1.53 2007/02/07 23:11:30 tgl Exp $
14 #include "libpq/pqcomm.h"
15 #include "utils/hsearch.h"
16 #include "utils/rel.h"
17 #include "utils/timestamp.h"
21 * The types of backend -> collector messages
24 typedef enum StatMsgType
28 PGSTAT_MTYPE_TABPURGE,
30 PGSTAT_MTYPE_RESETCOUNTER,
31 PGSTAT_MTYPE_AUTOVAC_START,
37 * The data type used for counters.
40 typedef int64 PgStat_Counter;
43 /* ------------------------------------------------------------
44 * Message formats follow
45 * ------------------------------------------------------------
50 * PgStat_MsgHdr The common message header
53 typedef struct PgStat_MsgHdr
60 * Space available in a message. This will keep the UDP packets below 1K,
61 * which should fit unfragmented into the MTU of the lo interface on most
62 * platforms. Does anybody care for platforms where it doesn't?
65 #define PGSTAT_MSG_PAYLOAD (1000 - sizeof(PgStat_MsgHdr))
69 * PgStat_MsgDummy A dummy message, ignored by the collector
72 typedef struct PgStat_MsgDummy
79 * PgStat_TableEntry Per-table info in a MsgTabstat
81 * Note: for a table, tuples_returned is the number of tuples successfully
82 * fetched by heap_getnext, while tuples_fetched is the number of tuples
83 * successfully fetched by heap_fetch under the control of bitmap indexscans.
84 * For an index, tuples_returned is the number of index entries returned by
85 * the index AM, while tuples_fetched is the number of tuples successfully
86 * fetched by heap_fetch under the control of simple indexscans for this index.
89 typedef struct PgStat_TableEntry
93 PgStat_Counter t_numscans;
95 PgStat_Counter t_tuples_returned;
96 PgStat_Counter t_tuples_fetched;
98 PgStat_Counter t_tuples_inserted;
99 PgStat_Counter t_tuples_updated;
100 PgStat_Counter t_tuples_deleted;
102 PgStat_Counter t_blocks_fetched;
103 PgStat_Counter t_blocks_hit;
107 * PgStat_MsgTabstat Sent by the backend to report table
108 * and buffer access statistics.
111 #define PGSTAT_NUM_TABENTRIES \
112 ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int)) \
113 / sizeof(PgStat_TableEntry))
115 typedef struct PgStat_MsgTabstat
122 PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
127 * PgStat_MsgTabpurge Sent by the backend to tell the collector
131 #define PGSTAT_NUM_TABPURGE \
132 ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int)) \
135 typedef struct PgStat_MsgTabpurge
140 Oid m_tableid[PGSTAT_NUM_TABPURGE];
141 } PgStat_MsgTabpurge;
145 * PgStat_MsgDropdb Sent by the backend to tell the collector
146 * about a dropped database
149 typedef struct PgStat_MsgDropdb
157 * PgStat_MsgResetcounter Sent by the backend to tell the collector
161 typedef struct PgStat_MsgResetcounter
165 } PgStat_MsgResetcounter;
169 * PgStat_MsgAutovacStart Sent by the autovacuum daemon to signal
170 * that a database is going to be processed
173 typedef struct PgStat_MsgAutovacStart
177 TimestampTz m_start_time;
178 } PgStat_MsgAutovacStart;
182 * PgStat_MsgVacuum Sent by the backend or autovacuum daemon
183 * after VACUUM or VACUUM ANALYZE
186 typedef struct PgStat_MsgVacuum
193 TimestampTz m_vacuumtime;
194 PgStat_Counter m_tuples;
199 * PgStat_MsgAnalyze Sent by the backend or autovacuum daemon
203 typedef struct PgStat_MsgAnalyze
209 TimestampTz m_analyzetime;
210 PgStat_Counter m_live_tuples;
211 PgStat_Counter m_dead_tuples;
216 * PgStat_Msg Union over all possible messages.
219 typedef union PgStat_Msg
221 PgStat_MsgHdr msg_hdr;
222 PgStat_MsgDummy msg_dummy;
223 PgStat_MsgTabstat msg_tabstat;
224 PgStat_MsgTabpurge msg_tabpurge;
225 PgStat_MsgDropdb msg_dropdb;
226 PgStat_MsgResetcounter msg_resetcounter;
227 PgStat_MsgAutovacStart msg_autovacuum;
228 PgStat_MsgVacuum msg_vacuum;
229 PgStat_MsgAnalyze msg_analyze;
233 /* ------------------------------------------------------------
234 * Statistic collector data structures follow
236 * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
237 * data structures change.
238 * ------------------------------------------------------------
241 #define PGSTAT_FILE_FORMAT_ID 0x01A5BC96
244 * PgStat_StatDBEntry The collector's data per database
247 typedef struct PgStat_StatDBEntry
250 PgStat_Counter n_xact_commit;
251 PgStat_Counter n_xact_rollback;
252 PgStat_Counter n_blocks_fetched;
253 PgStat_Counter n_blocks_hit;
254 TimestampTz last_autovac_time;
257 * tables must be last in the struct, because we don't write the pointer
258 * out to the stats file.
261 } PgStat_StatDBEntry;
265 * PgStat_StatTabEntry The collector's data per table (or index)
268 typedef struct PgStat_StatTabEntry
272 PgStat_Counter numscans;
274 PgStat_Counter tuples_returned;
275 PgStat_Counter tuples_fetched;
277 PgStat_Counter tuples_inserted;
278 PgStat_Counter tuples_updated;
279 PgStat_Counter tuples_deleted;
281 PgStat_Counter n_live_tuples;
282 PgStat_Counter n_dead_tuples;
283 PgStat_Counter last_anl_tuples;
285 PgStat_Counter blocks_fetched;
286 PgStat_Counter blocks_hit;
288 TimestampTz vacuum_timestamp; /* user initiated vacuum */
289 TimestampTz autovac_vacuum_timestamp; /* autovacuum initiated */
290 TimestampTz analyze_timestamp; /* user initiated */
291 TimestampTz autovac_analyze_timestamp; /* autovacuum initiated */
292 } PgStat_StatTabEntry;
296 * Shared-memory data structures
300 /* Max length of st_activity string ... perhaps replace with a GUC var? */
301 #define PGBE_ACTIVITY_SIZE 1024
306 * Each live backend maintains a PgBackendStatus struct in shared memory
307 * showing its current activity. (The structs are allocated according to
308 * BackendId, but that is not critical.) Note that the collector process
309 * has no involvement in, or even access to, these structs.
312 typedef struct PgBackendStatus
315 * To avoid locking overhead, we use the following protocol: a backend
316 * increments st_changecount before modifying its entry, and again after
317 * finishing a modification. A would-be reader should note the value of
318 * st_changecount, copy the entry into private memory, then check
319 * st_changecount again. If the value hasn't changed, and if it's even,
320 * the copy is valid; otherwise start over. This makes updates cheap
321 * while reads are potentially expensive, but that's the tradeoff we want.
325 /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
328 /* Times when current backend, transaction, and activity started */
329 TimestampTz st_proc_start_timestamp;
330 TimestampTz st_txn_start_timestamp;
331 TimestampTz st_activity_start_timestamp;
333 /* Database OID, owning user's OID, connection client address */
336 SockAddr st_clientaddr;
338 /* Is backend currently waiting on an lmgr lock? */
341 /* current command string; MUST be null-terminated */
342 char st_activity[PGBE_ACTIVITY_SIZE];
350 extern bool pgstat_collect_startcollector;
351 extern bool pgstat_collect_resetonpmstart;
352 extern bool pgstat_collect_tuplelevel;
353 extern bool pgstat_collect_blocklevel;
354 extern bool pgstat_collect_querystring;
358 * Functions called from postmaster
361 extern Size BackendStatusShmemSize(void);
362 extern void CreateSharedBackendStatus(void);
364 extern void pgstat_init(void);
365 extern int pgstat_start(void);
366 extern void pgstat_reset_all(void);
369 extern void PgstatCollectorMain(int argc, char *argv[]);
374 * Functions called from backends
377 extern void pgstat_ping(void);
379 extern void pgstat_report_tabstat(void);
380 extern void pgstat_vacuum_tabstat(void);
381 extern void pgstat_drop_relation(Oid relid);
383 extern void pgstat_clear_snapshot(void);
384 extern void pgstat_reset_counters(void);
386 extern void pgstat_report_autovac(Oid dboid);
387 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
388 bool analyze, PgStat_Counter tuples);
389 extern void pgstat_report_analyze(Oid tableoid, bool shared,
390 PgStat_Counter livetuples,
391 PgStat_Counter deadtuples);
393 extern void pgstat_bestart(void);
394 extern void pgstat_report_activity(const char *what);
395 extern void pgstat_report_txn_timestamp(TimestampTz tstamp);
396 extern void pgstat_report_waiting(bool waiting);
398 extern void pgstat_initstats(PgStat_Info *stats, Relation rel);
401 #define pgstat_count_heap_scan(s) \
403 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
404 ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++; \
406 /* kluge for bitmap scans: */
407 #define pgstat_discount_heap_scan(s) \
409 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
410 ((PgStat_TableEntry *)((s)->tabentry))->t_numscans--; \
412 #define pgstat_count_heap_getnext(s) \
414 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
415 ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
417 #define pgstat_count_heap_fetch(s) \
419 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
420 ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_fetched++; \
422 #define pgstat_count_heap_insert(s) \
424 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
425 ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_inserted++; \
427 #define pgstat_count_heap_update(s) \
429 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
430 ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_updated++; \
432 #define pgstat_count_heap_delete(s) \
434 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
435 ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_deleted++; \
437 #define pgstat_count_index_scan(s) \
439 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
440 ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++; \
442 #define pgstat_count_index_tuples(s, n) \
444 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL) \
445 ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned += (n); \
447 #define pgstat_count_buffer_read(s,r) \
449 if (pgstat_collect_blocklevel) { \
450 if ((s)->tabentry != NULL) \
451 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
453 pgstat_initstats((s), (r)); \
454 if ((s)->tabentry != NULL) \
455 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
459 #define pgstat_count_buffer_hit(s,r) \
461 if (pgstat_collect_blocklevel) { \
462 if ((s)->tabentry != NULL) \
463 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
465 pgstat_initstats((s), (r)); \
466 if ((s)->tabentry != NULL) \
467 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
473 extern void pgstat_count_xact_commit(void);
474 extern void pgstat_count_xact_rollback(void);
477 * Support functions for the SQL-callable functions to
478 * generate the pgstat* views.
481 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
482 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
483 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
484 extern int pgstat_fetch_stat_numbackends(void);
486 #endif /* PGSTAT_H */