]> granicus.if.org Git - postgresql/blob - src/include/pgstat.h
Clean up a number of autovacuum loose ends. Make the stats collector
[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.34 2005/07/29 19:30:09 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  */
75 typedef struct PgStat_TableEntry
76 {
77         Oid                     t_id;
78
79         PgStat_Counter t_numscans;
80
81         PgStat_Counter t_tuples_returned;
82         PgStat_Counter t_tuples_fetched;
83         PgStat_Counter t_tuples_inserted;
84         PgStat_Counter t_tuples_updated;
85         PgStat_Counter t_tuples_deleted;
86
87         PgStat_Counter t_blocks_fetched;
88         PgStat_Counter t_blocks_hit;
89 } PgStat_TableEntry;
90
91
92 /* ----------
93  * PgStat_MsgDummy                              A dummy message, ignored by the collector
94  * ----------
95  */
96 typedef struct PgStat_MsgDummy
97 {
98         PgStat_MsgHdr m_hdr;
99         char            m_dummy[512];
100 } PgStat_MsgDummy;
101
102 /* ----------
103  * PgStat_MsgBestart                    Sent by the backend on startup
104  * ----------
105  */
106 typedef struct PgStat_MsgBestart
107 {
108         PgStat_MsgHdr   m_hdr;
109         Oid                             m_databaseid;
110         Oid                     m_userid;
111         SockAddr                m_clientaddr;
112 } PgStat_MsgBestart;
113
114 /* ----------
115  * PgStat_MsgBeterm                             Sent by the postmaster after backend exit
116  * ----------
117  */
118 typedef struct PgStat_MsgBeterm
119 {
120         PgStat_MsgHdr m_hdr;
121 } PgStat_MsgBeterm;
122
123 /* ----------
124  * PgStat_MsgAutovacStart               Sent by the autovacuum daemon to signal
125  *                                                              that a database is going to be processed
126  * ----------
127  */
128 typedef struct PgStat_MsgAutovacStart
129 {
130         PgStat_MsgHdr m_hdr;
131         Oid                     m_databaseid;
132         TimestampTz     m_start_time;
133 } PgStat_MsgAutovacStart;
134
135 /* ----------
136  * PgStat_MsgVacuum                             Sent by the backend or autovacuum daemon
137  *                                                              after VACUUM or VACUUM ANALYZE
138  * ----------
139  */
140 typedef struct PgStat_MsgVacuum
141 {
142         PgStat_MsgHdr m_hdr;
143         Oid                     m_databaseid;
144         Oid                     m_tableoid;
145         bool            m_analyze;
146         PgStat_Counter m_tuples;
147 } PgStat_MsgVacuum;
148
149 /* ----------
150  * PgStat_MsgAnalyze                    Sent by the backend or autovacuum daemon
151  *                                                              after ANALYZE
152  * ----------
153  */
154 typedef struct PgStat_MsgAnalyze
155 {
156         PgStat_MsgHdr m_hdr;
157         Oid                     m_databaseid;
158         Oid                     m_tableoid;
159         PgStat_Counter  m_live_tuples;
160         PgStat_Counter  m_dead_tuples;
161 } PgStat_MsgAnalyze;
162
163
164 /* ----------
165  * PgStat_MsgActivity                   Sent by the backends when they start
166  *                                                              to parse a query.
167  * ----------
168  */
169 #define PGSTAT_ACTIVITY_SIZE    PGSTAT_MSG_PAYLOAD
170
171 typedef struct PgStat_MsgActivity
172 {
173         PgStat_MsgHdr m_hdr;
174         char            m_what[PGSTAT_ACTIVITY_SIZE];
175 } PgStat_MsgActivity;
176
177 /* ----------
178  * PgStat_MsgTabstat                    Sent by the backend to report table
179  *                                                              and buffer access statistics.
180  * ----------
181  */
182 #define PGSTAT_NUM_TABENTRIES   ((PGSTAT_MSG_PAYLOAD - 3 * sizeof(int))         \
183                                                                 / sizeof(PgStat_TableEntry))
184
185 typedef struct PgStat_MsgTabstat
186 {
187         PgStat_MsgHdr m_hdr;
188         Oid                     m_databaseid;
189         int                     m_nentries;
190         int                     m_xact_commit;
191         int                     m_xact_rollback;
192         PgStat_TableEntry m_entry[PGSTAT_NUM_TABENTRIES];
193 } PgStat_MsgTabstat;
194
195 /* ----------
196  * PgStat_MsgTabpurge                   Sent by the backend to tell the collector
197  *                                                              about dead tables.
198  * ----------
199  */
200 #define PGSTAT_NUM_TABPURGE             ((PGSTAT_MSG_PAYLOAD - sizeof(int))             \
201                                                                 / sizeof(Oid))
202
203 typedef struct PgStat_MsgTabpurge
204 {
205         PgStat_MsgHdr m_hdr;
206         Oid                     m_databaseid;
207         int                     m_nentries;
208         Oid                     m_tableid[PGSTAT_NUM_TABPURGE];
209 } PgStat_MsgTabpurge;
210
211
212 /* ----------
213  * PgStat_MsgDropdb                             Sent by the backend to tell the collector
214  *                                                              about dropped database
215  * ----------
216  */
217 typedef struct PgStat_MsgDropdb
218 {
219         PgStat_MsgHdr m_hdr;
220         Oid                     m_databaseid;
221 } PgStat_MsgDropdb;
222
223
224 /* ----------
225  * PgStat_MsgResetcounter               Sent by the backend to tell the collector
226  *                                                              to reset counters
227  * ----------
228  */
229 typedef struct PgStat_MsgResetcounter
230 {
231         PgStat_MsgHdr m_hdr;
232         Oid                     m_databaseid;
233 } PgStat_MsgResetcounter;
234
235
236 /* ----------
237  * PgStat_Msg                                   Union over all possible messages.
238  * ----------
239  */
240 typedef union PgStat_Msg
241 {
242         PgStat_MsgHdr msg_hdr;
243         PgStat_MsgDummy msg_dummy;
244         PgStat_MsgBestart msg_bestart;
245         PgStat_MsgActivity msg_activity;
246         PgStat_MsgTabstat msg_tabstat;
247         PgStat_MsgTabpurge msg_tabpurge;
248         PgStat_MsgDropdb msg_dropdb;
249         PgStat_MsgResetcounter msg_resetcounter;
250         PgStat_MsgAutovacStart msg_autovacuum;
251         PgStat_MsgVacuum msg_vacuum;
252         PgStat_MsgAnalyze msg_analyze;
253 } PgStat_Msg;
254
255
256 /* ------------------------------------------------------------
257  * Statistic collector data structures follow
258  *
259  * PGSTAT_FILE_FORMAT_ID should be changed whenever any of these
260  * data structures change.
261  * ------------------------------------------------------------
262  */
263
264 #define PGSTAT_FILE_FORMAT_ID   0x01A5BC93
265
266 /* ----------
267  * PgStat_StatDBEntry                   The collectors data per database
268  * ----------
269  */
270 typedef struct PgStat_StatDBEntry
271 {
272         Oid                     databaseid;
273         HTAB       *tables;
274         int                     n_backends;
275         PgStat_Counter n_xact_commit;
276         PgStat_Counter n_xact_rollback;
277         PgStat_Counter n_blocks_fetched;
278         PgStat_Counter n_blocks_hit;
279         int                     destroy;
280         TimestampTz     last_autovac_time;
281 } PgStat_StatDBEntry;
282
283
284 /* ----------
285  * PgStat_StatBeEntry                   The collectors data per backend
286  * ----------
287  */
288 typedef struct PgStat_StatBeEntry
289 {
290         /* An entry is non-empty iff procpid > 0 */
291         int                     procpid;
292         TimestampTz     start_timestamp;
293         TimestampTz     activity_start_timestamp;
294         char            activity[PGSTAT_ACTIVITY_SIZE];
295
296         /*
297          * The following fields are initialized by the BESTART message. If
298          * we have received messages from a backend before we have
299          * received its BESTART, these fields will be uninitialized:
300          * userid and databaseid will be InvalidOid, and clientaddr will
301          * be undefined.
302          */
303         Oid                     userid;
304         Oid                     databaseid;
305         SockAddr    clientaddr;
306 } PgStat_StatBeEntry;
307
308
309 /* ----------
310  * PgStat_StatBeDead                    Because UDP packets can arrive out of
311  *                                                              order, we need to keep some information
312  *                                                              about backends that are known to be
313  *                                                              dead for some seconds. This info is held
314  *                                                              in a hash table of these structs.
315  * ----------
316  */
317 typedef struct PgStat_StatBeDead
318 {
319         int                     procpid;
320         int                     backendid;
321         int                     destroy;
322 } PgStat_StatBeDead;
323
324
325 /* ----------
326  * PgStat_StatTabEntry                  The collectors data table data
327  * ----------
328  */
329 typedef struct PgStat_StatTabEntry
330 {
331         Oid                     tableid;
332
333         PgStat_Counter numscans;
334
335         PgStat_Counter tuples_returned;
336         PgStat_Counter tuples_fetched;
337         PgStat_Counter tuples_inserted;
338         PgStat_Counter tuples_updated;
339         PgStat_Counter tuples_deleted;
340
341         PgStat_Counter n_live_tuples;
342         PgStat_Counter n_dead_tuples;
343         PgStat_Counter last_anl_tuples;
344
345         PgStat_Counter blocks_fetched;
346         PgStat_Counter blocks_hit;
347
348         int                     destroy;
349 } PgStat_StatTabEntry;
350
351
352 /* ----------
353  * GUC parameters
354  * ----------
355  */
356 extern bool pgstat_collect_startcollector;
357 extern bool pgstat_collect_resetonpmstart;
358 extern bool pgstat_collect_querystring;
359 extern bool pgstat_collect_tuplelevel;
360 extern bool pgstat_collect_blocklevel;
361
362
363 /* ----------
364  * Functions called from postmaster
365  * ----------
366  */
367 extern void pgstat_init(void);
368 extern int      pgstat_start(void);
369 extern void pgstat_beterm(int pid);
370
371 #ifdef EXEC_BACKEND
372 extern void PgstatBufferMain(int argc, char *argv[]);
373 extern void PgstatCollectorMain(int argc, char *argv[]);
374 #endif
375
376
377 /* ----------
378  * Functions called from backends
379  * ----------
380  */
381 extern void pgstat_bestart(void);
382
383 extern void pgstat_ping(void);
384 extern void pgstat_report_activity(const char *what);
385 extern void pgstat_report_tabstat(void);
386 extern void pgstat_report_autovac(void);
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);
392 extern int      pgstat_vacuum_tabstat(void);
393
394 extern void pgstat_reset_counters(void);
395
396 extern void pgstat_initstats(PgStat_Info *stats, Relation rel);
397
398
399 #define pgstat_reset_heap_scan(s)                                                                               \
400         do {                                                                                                                            \
401                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
402                         (s)->heap_scan_counted = FALSE;                                                         \
403         } while (0)
404 #define pgstat_count_heap_scan(s)                                                                               \
405         do {                                                                                                                            \
406                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL &&               \
407                                 !(s)->heap_scan_counted) {                                                              \
408                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
409                         (s)->heap_scan_counted = TRUE;                                                          \
410                 }                                                                                                                               \
411         } while (0)
412 #define pgstat_count_heap_getnext(s)                                                                    \
413         do {                                                                                                                            \
414                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
415                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
416         } while (0)
417 #define pgstat_count_heap_fetch(s)                                                                              \
418         do {                                                                                                                            \
419                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
420                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_fetched++; \
421         } while (0)
422 #define pgstat_count_heap_insert(s)                                                                             \
423         do {                                                                                                                            \
424                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
425                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_inserted++; \
426         } while (0)
427 #define pgstat_count_heap_update(s)                                                                             \
428         do {                                                                                                                            \
429                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
430                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_updated++; \
431         } while (0)
432 #define pgstat_count_heap_delete(s)                                                                             \
433         do {                                                                                                                            \
434                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
435                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_deleted++; \
436         } while (0)
437 #define pgstat_reset_index_scan(s)                                                                              \
438         do {                                                                                                                            \
439                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
440                         (s)->index_scan_counted = FALSE;                                                        \
441         } while (0)
442 #define pgstat_count_index_scan(s)                                                                              \
443         do {                                                                                                                            \
444                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL &&               \
445                                 !(s)->index_scan_counted) {                                                             \
446                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
447                         (s)->index_scan_counted = TRUE;                                                         \
448                 }                                                                                                                               \
449         } while (0)
450 #define pgstat_count_index_getnext(s)                                                                   \
451         do {                                                                                                                            \
452                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
453                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
454         } while (0)
455 #define pgstat_count_buffer_read(s,r)                                                                   \
456         do {                                                                                                                            \
457                 if (pgstat_collect_blocklevel && (s)->tabentry != NULL)                 \
458                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
459                 else {                                                                                                                  \
460                         if (pgstat_collect_blocklevel && !(s)->no_stats) {                      \
461                                 pgstat_initstats((s), (r));                                                             \
462                                 if ((s)->tabentry != NULL)                                                              \
463                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
464                         }                                                                                                                       \
465                 }                                                                                                                               \
466         } while (0)
467 #define pgstat_count_buffer_hit(s,r)                                                                    \
468         do {                                                                                                                            \
469                 if (pgstat_collect_blocklevel && (s)->tabentry != NULL)                 \
470                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++;         \
471                 else {                                                                                                                  \
472                         if (pgstat_collect_blocklevel && !(s)->no_stats) {                      \
473                                 pgstat_initstats((s), (r));                                                             \
474                                 if ((s)->tabentry != NULL)                                                              \
475                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
476                         }                                                                                                                       \
477                 }                                                                                                                               \
478         } while (0)
479
480
481 extern void pgstat_count_xact_commit(void);
482 extern void pgstat_count_xact_rollback(void);
483
484 /* ----------
485  * Support functions for the SQL-callable functions to
486  * generate the pgstat* views.
487  * ----------
488  */
489 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
490 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
491 extern PgStat_StatBeEntry *pgstat_fetch_stat_beentry(int beid);
492 extern int      pgstat_fetch_stat_numbackends(void);
493
494 #endif   /* PGSTAT_H */