Re: Flush some statistics within running transactions

From: Sami Imseih <samimseih(at)gmail(dot)com>
To: Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com>
Cc: Bertrand Drouvot <bertranddrouvot(dot)pg(at)gmail(dot)com>, Michael Paquier <michael(at)paquier(dot)xyz>, Fujii Masao <masao(dot)fujii(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: Flush some statistics within running transactions
Date: 2026-02-04 20:15:02
Message-ID: CAA5RZ0vgts58i4M99q-zRdSiBiHMJ2p+c9S6sYqzWvsK6sSaGg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

> do { \
> + pgstat_report_mixed_anytime = true; \
> if (pgstat_should_count_relation(rel)) \
> (rel)->pgstat_info->counts.numscans++; \
>
> Shouldn't these pgstat_report_mixed_anytime changes go inside the if
> statement in all macros?

I think you are correct here, and there is an even more fundamental issue.

since
``
#define pgstat_should_count_relation(rel) \
(likely((rel)->pgstat_info != NULL) ? true : \
```
could return if there is already a pgstat_info, we may never actually
enable the timeout.

so, I think we should:

1/

remove the scheduling of the timeout from pgstat_prep_pending_entry

@@ -1308,11 +1308,6 @@ pgstat_prep_pending_entry(PgStat_Kind kind, Oid
dboid, uint64 objid, bool *creat

entry_ref->pending =
MemoryContextAllocZero(pgStatPendingContext, entrysize);
dlist_push_tail(&pgStatPending, &entry_ref->pending_node);
-
- /* Schedule next anytime stats update timeout */
- if ((kind_info->flush_mode == FLUSH_ANYTIME ||
pgstat_report_mixed_anytime) &&
- IsUnderPostmaster &&
!get_timeout_active(ANYTIME_STATS_UPDATE_TIMEOUT))
-
enable_timeout_after(ANYTIME_STATS_UPDATE_TIMEOUT,
pgstat_flush_interval);
}

2/

Create a routine to schedule the timeout:

+void
+ScheduleAnyTimeUpdate(void)
+{
+ /* Schedule next anytime stats update timeout */
+ if (IsUnderPostmaster &&
!get_timeout_active(ANYTIME_STATS_UPDATE_TIMEOUT))
+ enable_timeout_after(ANYTIME_STATS_UPDATE_TIMEOUT,
pgstat_flush_interval);
+
+ pgstat_report_mixed_anytime = true;
+}

This will also set pgstat_report_mixed_anytime to true. In my earlier
comments, I mentioned
having this as a public routine will be needed for extensions that
register a custom kind as well.

3/

All the count routines that wish to schedule any ANYTIME update because
their kind allows it can do so with ScheduleAnyTimeUpdate(). In the relation
stats, this can happen after it is checked that the relation should
track counts.

+#define pgstat_count_heap_scan(rel) \
+ do { \
+ if (pgstat_should_count_relation(rel)) \
+ { \
+ (rel)->pgstat_info->counts.numscans++; \
+ ScheduleAnyTimeUpdate(); \
+ } \
+ } while (0)

Also, it would be good to check if we have anytime flushes of either a mixed or
a fixed kind. Not strictly necessary, but I think it's better to avoid
needlessly entering
the flush routines.

@@ -2220,11 +2215,27 @@ pgstat_report_anytime_stat(bool force)

pgstat_assert_is_up();
/* Flush stats outside of transaction boundary */
- pgstat_flush_pending_entries(nowait, true);
- pgstat_flush_fixed_stats(nowait, true);
+ if (pgstat_report_mixed_anytime)
+ pgstat_flush_pending_entries(nowait, true);
+
+ if (pgstat_report_mixed_anytime)
+ pgstat_flush_fixed_stats(nowait, true);

pgstat_report_mixed_anytime = false;
+ pgstat_report_fixed = false;
}

I think we could benefit from a test that st track_counts to OFF inside
a transaction and re-enables it, to make sure the pgstat_should_count_relation
work is done correctly.

--
Sami Imseih
Amazon Web Services (AWS)

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Nathan Bossart 2026-02-04 20:22:29 Re: Pasword expiration warning
Previous Message Nathan Bossart 2026-02-04 20:08:47 Re: pg_upgrade: transfer pg_largeobject_metadata's files when possible