]> granicus.if.org Git - postgresql/blob - src/include/pgstat.h
a702ad828884dd051de5813892da51118404c004
[postgresql] / src / include / pgstat.h
1 /* ----------
2  *      pgstat.h
3  *
4  *      Definitions for the PostgreSQL statistics collector daemon.
5  *
6  *      Copyright (c) 2001-2006, PostgreSQL Global Development Group
7  *
8  *      $PostgreSQL: pgsql/src/include/pgstat.h,v 1.51 2006/12/06 18:06:47 neilc Exp $
9  * ----------
10  */
11 #ifndef PGSTAT_H
12 #define PGSTAT_H
13
14 #include "libpq/pqcomm.h"
15 #include "utils/hsearch.h"
16 #include "utils/rel.h"
17 #include "utils/timestamp.h"
18
19
20 /* ----------
21  * The types of backend -> collector messages
22  * ----------
23  */
24 typedef enum StatMsgType
25 {
26         PGSTAT_MTYPE_DUMMY,
27         PGSTAT_MTYPE_TABSTAT,
28         PGSTAT_MTYPE_TABPURGE,
29         PGSTAT_MTYPE_DROPDB,
30         PGSTAT_MTYPE_RESETCOUNTER,
31         PGSTAT_MTYPE_AUTOVAC_START,
32         PGSTAT_MTYPE_VACUUM,
33         PGSTAT_MTYPE_ANALYZE
34 } StatMsgType;
35
36 /* ----------
37  * The data type used for counters.
38  * ----------
39  */
40 typedef int64 PgStat_Counter;
41
42
43 /* ------------------------------------------------------------
44  * Message formats follow
45  * ------------------------------------------------------------
46  */
47
48
49 /* ----------
50  * PgStat_MsgHdr                                The common message header
51  * ----------
52  */
53 typedef struct PgStat_MsgHdr
54 {
55         StatMsgType m_type;
56         int                     m_size;
57 } PgStat_MsgHdr;
58
59 /* ----------
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?
63  * ----------
64  */
65 #define PGSTAT_MSG_PAYLOAD      (1000 - sizeof(PgStat_MsgHdr))
66
67
68 /* ----------
69  * PgStat_MsgDummy                              A dummy message, ignored by the collector
70  * ----------
71  */
72 typedef struct PgStat_MsgDummy
73 {
74         PgStat_MsgHdr m_hdr;
75 } PgStat_MsgDummy;
76
77
78 /* ----------
79  * PgStat_TableEntry                    Per-table info in a MsgTabstat
80  *
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.
87  * ----------
88  */
89 typedef struct PgStat_TableEntry
90 {
91         Oid                     t_id;
92
93         PgStat_Counter t_numscans;
94
95         PgStat_Counter t_tuples_returned;
96         PgStat_Counter t_tuples_fetched;
97
98         PgStat_Counter t_tuples_inserted;
99         PgStat_Counter t_tuples_updated;
100         PgStat_Counter t_tuples_deleted;
101
102         PgStat_Counter t_blocks_fetched;
103         PgStat_Counter t_blocks_hit;
104 } PgStat_TableEntry;
105
106 /* ----------
107  * PgStat_MsgTabstat                    Sent by the backend to report table
108  *                                                              and buffer access statistics.
109  * ----------
110  */
111 #define PGSTAT_NUM_TABENTRIES  \
112         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int))  \
113          / sizeof(PgStat_TableEntry))
114
115 typedef struct PgStat_MsgTabstat
116 {
117         PgStat_MsgHdr m_hdr;
118         Oid                     m_databaseid;
119         int                     m_nentries;
120         int                     m_xact_commit;
121         int                     m_xact_rollback;
122         PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
123 } PgStat_MsgTabstat;
124
125
126 /* ----------
127  * PgStat_MsgTabpurge                   Sent by the backend to tell the collector
128  *                                                              about dead tables.
129  * ----------
130  */
131 #define PGSTAT_NUM_TABPURGE  \
132         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int))  \
133          / sizeof(Oid))
134
135 typedef struct PgStat_MsgTabpurge
136 {
137         PgStat_MsgHdr m_hdr;
138         Oid                     m_databaseid;
139         int                     m_nentries;
140         Oid                     m_tableid[PGSTAT_NUM_TABPURGE];
141 } PgStat_MsgTabpurge;
142
143
144 /* ----------
145  * PgStat_MsgDropdb                             Sent by the backend to tell the collector
146  *                                                              about a dropped database
147  * ----------
148  */
149 typedef struct PgStat_MsgDropdb
150 {
151         PgStat_MsgHdr m_hdr;
152         Oid                     m_databaseid;
153 } PgStat_MsgDropdb;
154
155
156 /* ----------
157  * PgStat_MsgResetcounter               Sent by the backend to tell the collector
158  *                                                              to reset counters
159  * ----------
160  */
161 typedef struct PgStat_MsgResetcounter
162 {
163         PgStat_MsgHdr m_hdr;
164         Oid                     m_databaseid;
165 } PgStat_MsgResetcounter;
166
167
168 /* ----------
169  * PgStat_MsgAutovacStart               Sent by the autovacuum daemon to signal
170  *                                                              that a database is going to be processed
171  * ----------
172  */
173 typedef struct PgStat_MsgAutovacStart
174 {
175         PgStat_MsgHdr m_hdr;
176         Oid                     m_databaseid;
177         TimestampTz m_start_time;
178 } PgStat_MsgAutovacStart;
179
180
181 /* ----------
182  * PgStat_MsgVacuum                             Sent by the backend or autovacuum daemon
183  *                                                              after VACUUM or VACUUM ANALYZE
184  * ----------
185  */
186 typedef struct PgStat_MsgVacuum
187 {
188         PgStat_MsgHdr m_hdr;
189         Oid                     m_databaseid;
190         Oid                     m_tableoid;
191         bool            m_analyze;
192         bool            m_autovacuum;
193         TimestampTz m_vacuumtime;
194         PgStat_Counter m_tuples;
195 } PgStat_MsgVacuum;
196
197
198 /* ----------
199  * PgStat_MsgAnalyze                    Sent by the backend or autovacuum daemon
200  *                                                              after ANALYZE
201  * ----------
202  */
203 typedef struct PgStat_MsgAnalyze
204 {
205         PgStat_MsgHdr m_hdr;
206         Oid                     m_databaseid;
207         Oid                     m_tableoid;
208         bool            m_autovacuum;
209         TimestampTz m_analyzetime;
210         PgStat_Counter m_live_tuples;
211         PgStat_Counter m_dead_tuples;
212 } PgStat_MsgAnalyze;
213
214
215 /* ----------
216  * PgStat_Msg                                   Union over all possible messages.
217  * ----------
218  */
219 typedef union PgStat_Msg
220 {
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;
230 } PgStat_Msg;
231
232
233 /* ------------------------------------------------------------
234  * Statistic collector data structures follow
235  *
236  * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
237  * data structures change.
238  * ------------------------------------------------------------
239  */
240
241 #define PGSTAT_FILE_FORMAT_ID   0x01A5BC96
242
243 /* ----------
244  * PgStat_StatDBEntry                   The collector's data per database
245  * ----------
246  */
247 typedef struct PgStat_StatDBEntry
248 {
249         Oid                     databaseid;
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;
255
256         /*
257          * tables must be last in the struct, because we don't write the pointer
258          * out to the stats file.
259          */
260         HTAB       *tables;
261 } PgStat_StatDBEntry;
262
263
264 /* ----------
265  * PgStat_StatTabEntry                  The collector's data per table (or index)
266  * ----------
267  */
268 typedef struct PgStat_StatTabEntry
269 {
270         Oid                     tableid;
271
272         PgStat_Counter numscans;
273
274         PgStat_Counter tuples_returned;
275         PgStat_Counter tuples_fetched;
276
277         PgStat_Counter tuples_inserted;
278         PgStat_Counter tuples_updated;
279         PgStat_Counter tuples_deleted;
280
281         PgStat_Counter n_live_tuples;
282         PgStat_Counter n_dead_tuples;
283         PgStat_Counter last_anl_tuples;
284
285         PgStat_Counter blocks_fetched;
286         PgStat_Counter blocks_hit;
287
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;
293
294
295 /* ----------
296  * Shared-memory data structures
297  * ----------
298  */
299
300 /* Max length of st_activity string ... perhaps replace with a GUC var? */
301 #define PGBE_ACTIVITY_SIZE      1024
302
303 /* ----------
304  * PgBackendStatus
305  *
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.
310  * ----------
311  */
312 typedef struct PgBackendStatus
313 {
314         /*
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.
322          */
323         int                     st_changecount;
324
325         /* The entry is valid iff st_procpid > 0, unused if st_procpid == 0 */
326         int                     st_procpid;
327
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;
332
333         /* Database OID, owning user's OID, connection client address */
334         Oid                     st_databaseid;
335         Oid                     st_userid;
336         SockAddr        st_clientaddr;
337
338         /* Is backend currently waiting on an lmgr lock? */
339         bool            st_waiting;
340
341         /* current command string; MUST be null-terminated */
342         char            st_activity[PGBE_ACTIVITY_SIZE];
343 } PgBackendStatus;
344
345
346 /* ----------
347  * GUC parameters
348  * ----------
349  */
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;
355
356
357 /* ----------
358  * Functions called from postmaster
359  * ----------
360  */
361 extern Size BackendStatusShmemSize(void);
362 extern void CreateSharedBackendStatus(void);
363
364 extern void pgstat_init(void);
365 extern int      pgstat_start(void);
366 extern void pgstat_reset_all(void);
367
368 #ifdef EXEC_BACKEND
369 extern void PgstatCollectorMain(int argc, char *argv[]);
370 #endif
371
372
373 /* ----------
374  * Functions called from backends
375  * ----------
376  */
377 extern void pgstat_ping(void);
378
379 extern void pgstat_report_tabstat(void);
380 extern void pgstat_vacuum_tabstat(void);
381 extern void pgstat_drop_relation(Oid relid);
382
383 extern void pgstat_reset_counters(void);
384
385 extern void pgstat_report_autovac(Oid dboid);
386 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
387                                          bool analyze, PgStat_Counter tuples);
388 extern void pgstat_report_analyze(Oid tableoid, bool shared,
389                                           PgStat_Counter livetuples,
390                                           PgStat_Counter deadtuples);
391
392 extern void pgstat_bestart(void);
393 extern void pgstat_report_activity(const char *what);
394 extern void pgstat_report_txn_timestamp(TimestampTz tstamp);
395 extern void pgstat_report_waiting(bool waiting);
396
397 extern void pgstat_initstats(PgStat_Info *stats, Relation rel);
398
399
400 #define pgstat_count_heap_scan(s)                                                                               \
401         do {                                                                                                                            \
402                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
403                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
404         } while (0)
405 /* kluge for bitmap scans: */
406 #define pgstat_discount_heap_scan(s)                                                                    \
407         do {                                                                                                                            \
408                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
409                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans--;           \
410         } while (0)
411 #define pgstat_count_heap_getnext(s)                                                                    \
412         do {                                                                                                                            \
413                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
414                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
415         } while (0)
416 #define pgstat_count_heap_fetch(s)                                                                              \
417         do {                                                                                                                            \
418                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
419                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_fetched++; \
420         } while (0)
421 #define pgstat_count_heap_insert(s)                                                                             \
422         do {                                                                                                                            \
423                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
424                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_inserted++; \
425         } while (0)
426 #define pgstat_count_heap_update(s)                                                                             \
427         do {                                                                                                                            \
428                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
429                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_updated++; \
430         } while (0)
431 #define pgstat_count_heap_delete(s)                                                                             \
432         do {                                                                                                                            \
433                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
434                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_deleted++; \
435         } while (0)
436 #define pgstat_count_index_scan(s)                                                                              \
437         do {                                                                                                                            \
438                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
439                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
440         } while (0)
441 #define pgstat_count_index_tuples(s, n)                                                                 \
442         do {                                                                                                                            \
443                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
444                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned += (n); \
445         } while (0)
446 #define pgstat_count_buffer_read(s,r)                                                                   \
447         do {                                                                                                                            \
448                 if (pgstat_collect_blocklevel) {                                                                \
449                         if ((s)->tabentry != NULL)                                                                      \
450                                 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
451                         else {                                                                                                          \
452                                 pgstat_initstats((s), (r));                                                             \
453                                 if ((s)->tabentry != NULL)                                                              \
454                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
455                         }                                                                                                                       \
456                 }                                                                                                                               \
457         } while (0)
458 #define pgstat_count_buffer_hit(s,r)                                                                    \
459         do {                                                                                                                            \
460                 if (pgstat_collect_blocklevel) {                                                                \
461                         if ((s)->tabentry != NULL)                                                                      \
462                                 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
463                         else {                                                                                                          \
464                                 pgstat_initstats((s), (r));                                                             \
465                                 if ((s)->tabentry != NULL)                                                              \
466                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
467                         }                                                                                                                       \
468                 }                                                                                                                               \
469         } while (0)
470
471
472 extern void pgstat_count_xact_commit(void);
473 extern void pgstat_count_xact_rollback(void);
474
475 /* ----------
476  * Support functions for the SQL-callable functions to
477  * generate the pgstat* views.
478  * ----------
479  */
480 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
481 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
482 extern PgBackendStatus *pgstat_fetch_stat_beentry(int beid);
483 extern int      pgstat_fetch_stat_numbackends(void);
484
485 #endif   /* PGSTAT_H */