]> granicus.if.org Git - postgresql/blob - src/include/pgstat.h
Revise pgstats stuff to fix the problems with not counting accesses
[postgresql] / src / include / pgstat.h
1 /* ----------
2  *      pgstat.h
3  *
4  *      Definitions for the PostgreSQL statistics collector daemon.
5  *
6  *      Copyright (c) 2001-2005, PostgreSQL Global Development Group
7  *
8  *      $PostgreSQL: pgsql/src/include/pgstat.h,v 1.37 2005/10/06 02:29:19 tgl 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  * The types of backend/postmaster -> collector messages
21  * ----------
22  */
23 typedef enum StatMsgType
24 {
25         PGSTAT_MTYPE_DUMMY,
26         PGSTAT_MTYPE_BESTART,
27         PGSTAT_MTYPE_BETERM,
28         PGSTAT_MTYPE_ACTIVITY,
29         PGSTAT_MTYPE_TABSTAT,
30         PGSTAT_MTYPE_TABPURGE,
31         PGSTAT_MTYPE_DROPDB,
32         PGSTAT_MTYPE_RESETCOUNTER,
33         PGSTAT_MTYPE_AUTOVAC_START,
34         PGSTAT_MTYPE_VACUUM,
35         PGSTAT_MTYPE_ANALYZE
36 } StatMsgType;
37
38 /* ----------
39  * The data type used for counters.
40  * ----------
41  */
42 typedef int64 PgStat_Counter;
43
44
45 /* ------------------------------------------------------------
46  * Message formats follow
47  * ------------------------------------------------------------
48  */
49
50
51 /* ----------
52  * PgStat_MsgHdr                                The common message header
53  * ----------
54  */
55 typedef struct PgStat_MsgHdr
56 {
57         StatMsgType     m_type;
58         int                     m_size;
59         int                     m_backendid;
60         int                     m_procpid;
61 } PgStat_MsgHdr;
62
63 /* ----------
64  * Space available in a message.  This will keep the UDP packets below 1K,
65  * which should fit unfragmented into the MTU of the lo interface on most
66  * platforms. Does anybody care for platforms where it doesn't?
67  * ----------
68  */
69 #define PGSTAT_MSG_PAYLOAD      (1000 - sizeof(PgStat_MsgHdr))
70
71 /* ----------
72  * PgStat_TableEntry                    Per-table info in a MsgTabstat
73  *
74  * Note: for a table, tuples_returned is the number of tuples successfully
75  * fetched by heap_getnext, while tuples_fetched is the number of tuples
76  * successfully fetched by heap_fetch under the control of bitmap indexscans.
77  * For an index, tuples_returned is the number of index entries returned by
78  * the index AM, while tuples_fetched is the number of tuples successfully
79  * fetched by heap_fetch under the control of simple indexscans for this index.
80  * ----------
81  */
82 typedef struct PgStat_TableEntry
83 {
84         Oid                     t_id;
85
86         PgStat_Counter t_numscans;
87
88         PgStat_Counter t_tuples_returned;
89         PgStat_Counter t_tuples_fetched;
90
91         PgStat_Counter t_tuples_inserted;
92         PgStat_Counter t_tuples_updated;
93         PgStat_Counter t_tuples_deleted;
94
95         PgStat_Counter t_blocks_fetched;
96         PgStat_Counter t_blocks_hit;
97 } PgStat_TableEntry;
98
99
100 /* ----------
101  * PgStat_MsgDummy                              A dummy message, ignored by the collector
102  * ----------
103  */
104 typedef struct PgStat_MsgDummy
105 {
106         PgStat_MsgHdr m_hdr;
107         char            m_dummy[512];
108 } PgStat_MsgDummy;
109
110 /* ----------
111  * PgStat_MsgBestart                    Sent by the backend on startup
112  * ----------
113  */
114 typedef struct PgStat_MsgBestart
115 {
116         PgStat_MsgHdr   m_hdr;
117         Oid                             m_databaseid;
118         Oid                     m_userid;
119         SockAddr                m_clientaddr;
120 } PgStat_MsgBestart;
121
122 /* ----------
123  * PgStat_MsgBeterm                             Sent by the postmaster after backend exit
124  * ----------
125  */
126 typedef struct PgStat_MsgBeterm
127 {
128         PgStat_MsgHdr m_hdr;
129 } PgStat_MsgBeterm;
130
131 /* ----------
132  * PgStat_MsgAutovacStart               Sent by the autovacuum daemon to signal
133  *                                                              that a database is going to be processed
134  * ----------
135  */
136 typedef struct PgStat_MsgAutovacStart
137 {
138         PgStat_MsgHdr m_hdr;
139         Oid                     m_databaseid;
140         TimestampTz     m_start_time;
141 } PgStat_MsgAutovacStart;
142
143 /* ----------
144  * PgStat_MsgVacuum                             Sent by the backend or autovacuum daemon
145  *                                                              after VACUUM or VACUUM ANALYZE
146  * ----------
147  */
148 typedef struct PgStat_MsgVacuum
149 {
150         PgStat_MsgHdr m_hdr;
151         Oid                     m_databaseid;
152         Oid                     m_tableoid;
153         bool            m_analyze;
154         PgStat_Counter m_tuples;
155 } PgStat_MsgVacuum;
156
157 /* ----------
158  * PgStat_MsgAnalyze                    Sent by the backend or autovacuum daemon
159  *                                                              after ANALYZE
160  * ----------
161  */
162 typedef struct PgStat_MsgAnalyze
163 {
164         PgStat_MsgHdr m_hdr;
165         Oid                     m_databaseid;
166         Oid                     m_tableoid;
167         PgStat_Counter  m_live_tuples;
168         PgStat_Counter  m_dead_tuples;
169 } PgStat_MsgAnalyze;
170
171
172 /* ----------
173  * PgStat_MsgActivity                   Sent by the backends when they start
174  *                                                              to parse a query.
175  * ----------
176  */
177 #define PGSTAT_ACTIVITY_SIZE    PGSTAT_MSG_PAYLOAD
178
179 typedef struct PgStat_MsgActivity
180 {
181         PgStat_MsgHdr m_hdr;
182         char            m_what[PGSTAT_ACTIVITY_SIZE];
183 } PgStat_MsgActivity;
184
185 /* ----------
186  * PgStat_MsgTabstat                    Sent by the backend to report table
187  *                                                              and buffer access statistics.
188  * ----------
189  */
190 #define PGSTAT_NUM_TABENTRIES  \
191         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - 3 * sizeof(int))  \
192          / sizeof(PgStat_TableEntry))
193
194 typedef struct PgStat_MsgTabstat
195 {
196         PgStat_MsgHdr m_hdr;
197         Oid                     m_databaseid;
198         int                     m_nentries;
199         int                     m_xact_commit;
200         int                     m_xact_rollback;
201         PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
202 } PgStat_MsgTabstat;
203
204 /* ----------
205  * PgStat_MsgTabpurge                   Sent by the backend to tell the collector
206  *                                                              about dead tables.
207  * ----------
208  */
209 #define PGSTAT_NUM_TABPURGE  \
210         ((PGSTAT_MSG_PAYLOAD - sizeof(Oid) - sizeof(int))  \
211          / sizeof(Oid))
212
213 typedef struct PgStat_MsgTabpurge
214 {
215         PgStat_MsgHdr m_hdr;
216         Oid                     m_databaseid;
217         int                     m_nentries;
218         Oid                     m_tableid[PGSTAT_NUM_TABPURGE];
219 } PgStat_MsgTabpurge;
220
221
222 /* ----------
223  * PgStat_MsgDropdb                             Sent by the backend to tell the collector
224  *                                                              about a dropped database
225  * ----------
226  */
227 typedef struct PgStat_MsgDropdb
228 {
229         PgStat_MsgHdr m_hdr;
230         Oid                     m_databaseid;
231 } PgStat_MsgDropdb;
232
233
234 /* ----------
235  * PgStat_MsgResetcounter               Sent by the backend to tell the collector
236  *                                                              to reset counters
237  * ----------
238  */
239 typedef struct PgStat_MsgResetcounter
240 {
241         PgStat_MsgHdr m_hdr;
242         Oid                     m_databaseid;
243 } PgStat_MsgResetcounter;
244
245
246 /* ----------
247  * PgStat_Msg                                   Union over all possible messages.
248  * ----------
249  */
250 typedef union PgStat_Msg
251 {
252         PgStat_MsgHdr msg_hdr;
253         PgStat_MsgDummy msg_dummy;
254         PgStat_MsgBestart msg_bestart;
255         PgStat_MsgActivity msg_activity;
256         PgStat_MsgTabstat msg_tabstat;
257         PgStat_MsgTabpurge msg_tabpurge;
258         PgStat_MsgDropdb msg_dropdb;
259         PgStat_MsgResetcounter msg_resetcounter;
260         PgStat_MsgAutovacStart msg_autovacuum;
261         PgStat_MsgVacuum msg_vacuum;
262         PgStat_MsgAnalyze msg_analyze;
263 } PgStat_Msg;
264
265
266 /* ------------------------------------------------------------
267  * Statistic collector data structures follow
268  *
269  * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
270  * data structures change.
271  * ------------------------------------------------------------
272  */
273
274 #define PGSTAT_FILE_FORMAT_ID   0x01A5BC93
275
276 /* ----------
277  * PgStat_StatDBEntry                   The collector's data per database
278  * ----------
279  */
280 typedef struct PgStat_StatDBEntry
281 {
282         Oid                     databaseid;
283         HTAB       *tables;
284         int                     n_backends;
285         PgStat_Counter n_xact_commit;
286         PgStat_Counter n_xact_rollback;
287         PgStat_Counter n_blocks_fetched;
288         PgStat_Counter n_blocks_hit;
289         int                     destroy;
290         TimestampTz     last_autovac_time;
291 } PgStat_StatDBEntry;
292
293
294 /* ----------
295  * PgStat_StatBeEntry                   The collector's data per backend
296  * ----------
297  */
298 typedef struct PgStat_StatBeEntry
299 {
300         /* An entry is non-empty iff procpid > 0 */
301         int                     procpid;
302         TimestampTz     start_timestamp;
303         TimestampTz     activity_start_timestamp;
304         char            activity[PGSTAT_ACTIVITY_SIZE];
305
306         /*
307          * The following fields are initialized by the BESTART message. If
308          * we have received messages from a backend before we have
309          * received its BESTART, these fields will be uninitialized:
310          * userid and databaseid will be InvalidOid, and clientaddr will
311          * be undefined.
312          */
313         Oid                     userid;
314         Oid                     databaseid;
315         SockAddr    clientaddr;
316 } PgStat_StatBeEntry;
317
318
319 /* ----------
320  * PgStat_StatBeDead                    Because UDP packets can arrive out of
321  *                                                              order, we need to keep some information
322  *                                                              about backends that are known to be
323  *                                                              dead for some seconds. This info is held
324  *                                                              in a hash table of these structs.
325  * ----------
326  */
327 typedef struct PgStat_StatBeDead
328 {
329         int                     procpid;
330         int                     backendid;
331         int                     destroy;
332 } PgStat_StatBeDead;
333
334
335 /* ----------
336  * PgStat_StatTabEntry                  The collector's data per table (or index)
337  * ----------
338  */
339 typedef struct PgStat_StatTabEntry
340 {
341         Oid                     tableid;
342
343         PgStat_Counter numscans;
344
345         PgStat_Counter tuples_returned;
346         PgStat_Counter tuples_fetched;
347
348         PgStat_Counter tuples_inserted;
349         PgStat_Counter tuples_updated;
350         PgStat_Counter tuples_deleted;
351
352         PgStat_Counter n_live_tuples;
353         PgStat_Counter n_dead_tuples;
354         PgStat_Counter last_anl_tuples;
355
356         PgStat_Counter blocks_fetched;
357         PgStat_Counter blocks_hit;
358
359         int                     destroy;
360 } PgStat_StatTabEntry;
361
362
363 /* ----------
364  * GUC parameters
365  * ----------
366  */
367 extern bool pgstat_collect_startcollector;
368 extern bool pgstat_collect_resetonpmstart;
369 extern bool pgstat_collect_querystring;
370 extern bool pgstat_collect_tuplelevel;
371 extern bool pgstat_collect_blocklevel;
372
373
374 /* ----------
375  * Functions called from postmaster
376  * ----------
377  */
378 extern void pgstat_init(void);
379 extern int      pgstat_start(void);
380 extern void pgstat_beterm(int pid);
381 extern void pgstat_reset_all(void);
382
383 #ifdef EXEC_BACKEND
384 extern void PgstatBufferMain(int argc, char *argv[]);
385 extern void PgstatCollectorMain(int argc, char *argv[]);
386 #endif
387
388
389 /* ----------
390  * Functions called from backends
391  * ----------
392  */
393 extern void pgstat_bestart(void);
394
395 extern void pgstat_ping(void);
396 extern void pgstat_report_activity(const char *what);
397 extern void pgstat_report_tabstat(void);
398 extern void pgstat_report_autovac(Oid dboid);
399 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
400                                                                  bool analyze, PgStat_Counter tuples);
401 extern void pgstat_report_analyze(Oid tableoid, bool shared,
402                                                                   PgStat_Counter livetuples,
403                                                                   PgStat_Counter deadtuples);
404 extern int      pgstat_vacuum_tabstat(void);
405
406 extern void pgstat_reset_counters(void);
407
408 extern void pgstat_initstats(PgStat_Info *stats, Relation rel);
409
410
411 #define pgstat_count_heap_scan(s)                                                                               \
412         do {                                                                                                                            \
413                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
414                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
415         } while (0)
416 /* kluge for bitmap scans: */
417 #define pgstat_discount_heap_scan(s)                                                                    \
418         do {                                                                                                                            \
419                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
420                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans--;           \
421         } while (0)
422 #define pgstat_count_heap_getnext(s)                                                                    \
423         do {                                                                                                                            \
424                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
425                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
426         } while (0)
427 #define pgstat_count_heap_fetch(s)                                                                              \
428         do {                                                                                                                            \
429                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
430                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_fetched++; \
431         } while (0)
432 #define pgstat_count_heap_insert(s)                                                                             \
433         do {                                                                                                                            \
434                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
435                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_inserted++; \
436         } while (0)
437 #define pgstat_count_heap_update(s)                                                                             \
438         do {                                                                                                                            \
439                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
440                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_updated++; \
441         } while (0)
442 #define pgstat_count_heap_delete(s)                                                                             \
443         do {                                                                                                                            \
444                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
445                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_deleted++; \
446         } while (0)
447 #define pgstat_count_index_scan(s)                                                                              \
448         do {                                                                                                                            \
449                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
450                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
451         } while (0)
452 #define pgstat_count_index_tuples(s, n)                                                                 \
453         do {                                                                                                                            \
454                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
455                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned += (n); \
456         } while (0)
457 #define pgstat_count_buffer_read(s,r)                                                                   \
458         do {                                                                                                                            \
459                 if (pgstat_collect_blocklevel) {                                                                \
460                         if ((s)->tabentry != NULL)                                                                      \
461                                 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
462                         else {                                                                                                          \
463                                 pgstat_initstats((s), (r));                                                             \
464                                 if ((s)->tabentry != NULL)                                                              \
465                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
466                         }                                                                                                                       \
467                 }                                                                                                                               \
468         } while (0)
469 #define pgstat_count_buffer_hit(s,r)                                                                    \
470         do {                                                                                                                            \
471                 if (pgstat_collect_blocklevel) {                                                                \
472                         if ((s)->tabentry != NULL)                                                                      \
473                                 ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
474                         else {                                                                                                          \
475                                 pgstat_initstats((s), (r));                                                             \
476                                 if ((s)->tabentry != NULL)                                                              \
477                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
478                         }                                                                                                                       \
479                 }                                                                                                                               \
480         } while (0)
481
482
483 extern void pgstat_count_xact_commit(void);
484 extern void pgstat_count_xact_rollback(void);
485
486 /* ----------
487  * Support functions for the SQL-callable functions to
488  * generate the pgstat* views.
489  * ----------
490  */
491 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
492 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
493 extern PgStat_StatBeEntry *pgstat_fetch_stat_beentry(int beid);
494 extern int      pgstat_fetch_stat_numbackends(void);
495
496 #endif   /* PGSTAT_H */