]> granicus.if.org Git - postgresql/blob - src/include/pgstat.h
Autovacuum loose end mop-up. Provide autovacuum-specific vacuum cost
[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.35 2005/08/11 21:11:49 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 extern void pgstat_reset_all(void);
371
372 #ifdef EXEC_BACKEND
373 extern void PgstatBufferMain(int argc, char *argv[]);
374 extern void PgstatCollectorMain(int argc, char *argv[]);
375 #endif
376
377
378 /* ----------
379  * Functions called from backends
380  * ----------
381  */
382 extern void pgstat_bestart(void);
383
384 extern void pgstat_ping(void);
385 extern void pgstat_report_activity(const char *what);
386 extern void pgstat_report_tabstat(void);
387 extern void pgstat_report_autovac(void);
388 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
389                                                                  bool analyze, PgStat_Counter tuples);
390 extern void pgstat_report_analyze(Oid tableoid, bool shared,
391                                                                   PgStat_Counter livetuples,
392                                                                   PgStat_Counter deadtuples);
393 extern int      pgstat_vacuum_tabstat(void);
394
395 extern void pgstat_reset_counters(void);
396
397 extern void pgstat_initstats(PgStat_Info *stats, Relation rel);
398
399
400 #define pgstat_reset_heap_scan(s)                                                                               \
401         do {                                                                                                                            \
402                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
403                         (s)->heap_scan_counted = FALSE;                                                         \
404         } while (0)
405 #define pgstat_count_heap_scan(s)                                                                               \
406         do {                                                                                                                            \
407                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL &&               \
408                                 !(s)->heap_scan_counted) {                                                              \
409                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
410                         (s)->heap_scan_counted = TRUE;                                                          \
411                 }                                                                                                                               \
412         } while (0)
413 #define pgstat_count_heap_getnext(s)                                                                    \
414         do {                                                                                                                            \
415                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
416                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
417         } while (0)
418 #define pgstat_count_heap_fetch(s)                                                                              \
419         do {                                                                                                                            \
420                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
421                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_fetched++; \
422         } while (0)
423 #define pgstat_count_heap_insert(s)                                                                             \
424         do {                                                                                                                            \
425                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
426                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_inserted++; \
427         } while (0)
428 #define pgstat_count_heap_update(s)                                                                             \
429         do {                                                                                                                            \
430                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
431                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_updated++; \
432         } while (0)
433 #define pgstat_count_heap_delete(s)                                                                             \
434         do {                                                                                                                            \
435                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
436                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_deleted++; \
437         } while (0)
438 #define pgstat_reset_index_scan(s)                                                                              \
439         do {                                                                                                                            \
440                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
441                         (s)->index_scan_counted = FALSE;                                                        \
442         } while (0)
443 #define pgstat_count_index_scan(s)                                                                              \
444         do {                                                                                                                            \
445                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL &&               \
446                                 !(s)->index_scan_counted) {                                                             \
447                         ((PgStat_TableEntry *)((s)->tabentry))->t_numscans++;           \
448                         (s)->index_scan_counted = TRUE;                                                         \
449                 }                                                                                                                               \
450         } while (0)
451 #define pgstat_count_index_getnext(s)                                                                   \
452         do {                                                                                                                            \
453                 if (pgstat_collect_tuplelevel && (s)->tabentry != NULL)                 \
454                         ((PgStat_TableEntry *)((s)->tabentry))->t_tuples_returned++; \
455         } while (0)
456 #define pgstat_count_buffer_read(s,r)                                                                   \
457         do {                                                                                                                            \
458                 if (pgstat_collect_blocklevel && (s)->tabentry != NULL)                 \
459                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
460                 else {                                                                                                                  \
461                         if (pgstat_collect_blocklevel && !(s)->no_stats) {                      \
462                                 pgstat_initstats((s), (r));                                                             \
463                                 if ((s)->tabentry != NULL)                                                              \
464                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_fetched++; \
465                         }                                                                                                                       \
466                 }                                                                                                                               \
467         } while (0)
468 #define pgstat_count_buffer_hit(s,r)                                                                    \
469         do {                                                                                                                            \
470                 if (pgstat_collect_blocklevel && (s)->tabentry != NULL)                 \
471                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++;         \
472                 else {                                                                                                                  \
473                         if (pgstat_collect_blocklevel && !(s)->no_stats) {                      \
474                                 pgstat_initstats((s), (r));                                                             \
475                                 if ((s)->tabentry != NULL)                                                              \
476                                         ((PgStat_TableEntry *)((s)->tabentry))->t_blocks_hit++; \
477                         }                                                                                                                       \
478                 }                                                                                                                               \
479         } while (0)
480
481
482 extern void pgstat_count_xact_commit(void);
483 extern void pgstat_count_xact_rollback(void);
484
485 /* ----------
486  * Support functions for the SQL-callable functions to
487  * generate the pgstat* views.
488  * ----------
489  */
490 extern PgStat_StatDBEntry *pgstat_fetch_stat_dbentry(Oid dbid);
491 extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid);
492 extern PgStat_StatBeEntry *pgstat_fetch_stat_beentry(int beid);
493 extern int      pgstat_fetch_stat_numbackends(void);
494
495 #endif   /* PGSTAT_H */