Thread: Use pgBufferUsage for block reporting in analyze

Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
Hi,

Analyze logs within autovacuum uses specific variables VacuumPage{Hit,Miss,Dirty} to track the buffer usage count. However, pgBufferUsage already provides block usage tracking and handles more cases (temporary tables, parallel workers...).

Those variables were only used in two places, block usage reporting in verbose vacuum and analyze. 5cd72cc0c5017a9d4de8b5d465a75946da5abd1d removed their usage in the vacuum command as part of a bugfix. 

This patch replaces those Vacuum specific variables by pgBufferUsage in analyze. This makes VacuumPage{Hit,Miss,Dirty} unused and removable. This commit removes both their calls in bufmgr and their declarations.

Regards,
Anthonin
Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Michael Paquier
Date:
On Fri, May 10, 2024 at 10:54:07AM +0200, Anthonin Bonnefoy wrote:
> This patch replaces those Vacuum specific variables by pgBufferUsage
> in analyze. This makes VacuumPage{Hit,Miss,Dirty} unused and removable.
> This commit removes both their calls in bufmgr and their declarations.

Hmm, yeah, it looks like you're right.  I can track all the blocks
read, hit and dirtied for VACUUM and ANALYZE in all the code path
where these removed variables were incremented.  This needs some
runtime check to make sure that the calculations are consistent before
and after the fact (cannot do that now).

             appendStringInfo(&buf, _("buffer usage: %lld hits, %lld misses, %lld dirtied\n"),
-                             (long long) AnalyzePageHit,
-                             (long long) AnalyzePageMiss,
-                             (long long) AnalyzePageDirty);
+                             (long long) (bufferusage.shared_blks_hit + bufferusage.local_blks_hit),
+                             (long long) (bufferusage.shared_blks_read + bufferusage.local_blks_read),
+                             (long long) (bufferusage.shared_blks_dirtied + bufferusage.local_blks_dirtied));

Perhaps this should say "read" rather than "miss" in the logs as the
two read variables for the shared and local blocks are used?  For
consistency, at least.

That's not material for v17, only for v18.
--
Michael

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
Thanks for having a look.

On Fri, May 10, 2024 at 12:40 PM Michael Paquier <michael@paquier.xyz> wrote:
This needs some runtime check to make sure that the calculations 
are consistent before and after the fact (cannot do that now).
Yeah, testing this is also a bit painful as buffer usage of analyze is only displayed in the logs during autoanalyze. While looking at this, I've thought of additional changes that could make testing easier and improve consistency with VACUUM VERBOSE:
- Have ANALYZE VERBOSE outputs the buffer usage stats
- Add Wal usage to ANALYZE VERBOSE

analyze verbose output would look like: 
postgres=# analyze (verbose) pgbench_accounts ;
INFO:  analyzing "public.pgbench_accounts"
INFO:  "pgbench_accounts": scanned 1640 of 1640 pages, containing 100000 live rows and 0 dead rows; 30000 rows in sample, 100000 estimated total rows
INFO:  analyze of table "postgres.public.pgbench_accounts"
avg read rate: 124.120 MB/s, avg write rate: 0.110 MB/s
buffer usage: 533 hits, 1128 reads, 1 dirtied
WAL usage: 12 records, 1 full page images, 5729 bytes
system usage: CPU: user: 0.06 s, system: 0.00 s, elapsed: 0.07 s 

Perhaps this should say "read" rather than "miss" in the logs as the
two read variables for the shared and local blocks are used?  For
consistency, at least.
Sounds good. 

That's not material for v17, only for v18.
 Definitely

I've split the patch in two parts
1: Removal of the vacuum specific variables, this is the same as the initial patch.
2: Add buffer and wal usage to analyze verbose output + rename miss to reads 

Regards,
Anthonin
Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Karina Litskevich
Date:
Hi Anthonin,

I suggest assigning values
bufferusage.shared_blks_read + bufferusage.local_blks_read
and
bufferusage.shared_blks_dirtied + bufferusage.local_blks_dirtied
to new variables and using them. This would keep the changed lines within
the 80 symbols limit, and make the code more readable overall.

I also believe that changing "misses" to "reads" should belong to 0001
patch since we only change it because we replace AnalyzePageMiss with
bufferusage.shared_blks_read + bufferusage.local_blks_read in 0001.

Best regards,
Karina Litskevich
Postgres Professional: http://postgrespro.com/

Re: Use pgBufferUsage for block reporting in analyze

From
Karina Litskevich
Date:
I wrote:

I suggest assigning values
bufferusage.shared_blks_read + bufferusage.local_blks_read
and
bufferusage.shared_blks_dirtied + bufferusage.local_blks_dirtied
to new variables and using them. This would keep the changed lines within
the 80 symbols limit, and make the code more readable overall.

The same applies to
bufferusage.shared_blks_hit + bufferusage.local_blks_hit

Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
Hi,

Thanks for the review, I've updated the patches with the suggestions:
- moved renaming of misses to reads to the first patch
- added intermediate variables for total blks usage

I've also done some additional tests using the provided
vacuum_analyze_buffer_usage.sql script. It relies on
pg_stat_statements to check the results (only pgss gives information
on dirtied buffers). It gives the following output:

 psql:vacuum_analyze_buffer_usage.sql:21: INFO:  vacuuming
"postgres.pg_temp_7.vacuum_blks_stat_test"
 ...
 buffer usage: 105 hits, 3 reads, 6 dirtied
 ...
              query  | sum_hit | sum_read | sum_dirtied
 --------------------+---------+----------+-------------
  VACUUM (VERBOSE... |     105 |        3 |           6

For vacuum, we have the same results with SKIP_DATABASE_STATS. Without
this setting, we would have block usage generated by
vac_update_datfrozenxid outside of vacuum_rel and therefore not
tracked by the verbose output. For the second test, the second patch
is needed to have ANALYZE (VERBOSE) output the block usage. It will
output the following:

 psql:vacuum_analyze_buffer_usage.sql:29: INFO:  analyzing
"pg_temp_7.vacuum_blks_stat_test"
 ...
 buffer usage: 84 hits, 33 reads, 2 dirtied
 ...
     query            | sum_hit | sum_read | sum_dirtied
 ---------------------+---------+----------+-------------
  ANALYZE (VERBOSE... |      91 |       38 |           2

There's additional buffer hits/reads reported by pgss, those are from
analyze_rel opening the relations in try_relation_open and are not
tracked by the ANALYZE VERBOSE.

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Masahiko Sawada
Date:
On Mon, Jul 8, 2024 at 2:35 AM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
>
> Hi,
>
> Thanks for the review, I've updated the patches with the suggestions:
> - moved renaming of misses to reads to the first patch
> - added intermediate variables for total blks usage
>

Thank you for working on this. 0001 patch looks good to me.

I like the 0002 patch idea. But with this patch, ANALYZE VERBOSE
writes something like this:

INFO:  analyzing "public.test"
INFO:  "test": scanned 443 of 443 pages, containing 100000 live rows
and 0 dead rows; 30000 rows in sample, 100000 estimated total rows
INFO:  analyze of table "postgres.public.test"
avg read rate: 38.446 MB/s, avg write rate: 0.000 MB/s
buffer usage: 265 hits, 187 reads, 0 dirtied
WAL usage: 4 records, 0 full page images, 637 bytes
system usage: CPU: user: 0.03 s, system: 0.00 s, elapsed: 0.03 s

Which seems not to be consistent with what we do in VACUUM VERBOSE in
some points. For example, in VACUUM VERBOSE outputs, we write
statistics of pages, tuples, buffer usage, and WAL usage in one INFO
message:

INFO:  vacuuming "postgres.public.test"
INFO:  finished vacuuming "postgres.public.test": index scans: 0
pages: 0 removed, 443 remain, 1 scanned (0.23% of total)
tuples: 0 removed, 100000 remain, 0 are dead but not yet removable
removable cutoff: 754, which was 0 XIDs old when operation ended
frozen: 0 pages from table (0.00% of total) had 0 tuples frozen
index scan not needed: 0 pages from table (0.00% of total) had 0 dead
item identifiers removed
avg read rate: 23.438 MB/s, avg write rate: 0.000 MB/s
buffer usage: 5 hits, 3 reads, 0 dirtied
WAL usage: 0 records, 0 full page images, 0 bytes
system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s

I'd suggest writing analyze verbose messages as something like:

INFO: finished analyzing "postgres.public.test"
pages: 443 of 443 scanned
tuples: 100000 live tuples, 0 are dead; 30000 tuples in sample, 100000
estimated total tuples
avg read rate: 38.446 MB/s, avg write rate: 0.000 MB/s
buffer usage: 265 hits, 187 reads, 0 dirtied
WAL usage: 4 records, 0 full page images, 637 bytes
system usage: CPU: user: 0.03 s, system: 0.00 s, elapsed: 0.03 s

The first line would vary depending on whether an autovacuum worker or
not. And the above suggestion includes a change of term "row" to
"tuple" for better consistency with VACUUM VERBOSE outputs. I think it
would be great if autoanalyze also writes logs in the same format.
IIUC with the patch, autoanalyze logs don't include the page and tuple
statistics.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
On Mon, Jul 22, 2024 at 10:59 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> The first line would vary depending on whether an autovacuum worker or
> not. And the above suggestion includes a change of term "row" to
> "tuple" for better consistency with VACUUM VERBOSE outputs. I think it
> would be great if autoanalyze also writes logs in the same format.
> IIUC with the patch, autoanalyze logs don't include the page and tuple
> statistics.

One issue is that the number of scanned pages, live tuples and dead
tuples is only available in acquire_sample_rows which is where the log
containing those stats is emitted. I've tried to implement the
following in 0003:
- Sampling functions now accept an AcquireSampleStats struct to store
pages and tuples stats
- Log is removed from sampling functions
- do_analyze_rel now outputs scanned and tuples statistics when
relevant. sampling from fdw doesn't provide those statistics so they
are not displayed in those cases.

This ensures that analyze logs are only emitted in do_analyze_rel,
allowing to display the same output for both autoanalyze and ANALYZE
VERBOSE. With those changes, we have the following output for analyze
verbose of a table:

analyze (verbose) pgbench_accounts ;
INFO:  analyzing "public.pgbench_accounts"
INFO:  analyze of table "postgres.public.pgbench_accounts"
pages: 1640 of 1640 scanned
tuples: 100000 live tuples, 0 are dead; 30000 tuples in samples,
100000 estimated total tuples
avg read rate: 174.395 MB/s, avg write rate: 0.000 MB/s
buffer usage: 285 hits, 1384 reads, 0 dirtied
WAL usage: 14 records, 0 full page images, 1343 bytes
system usage: CPU: user: 0.05 s, system: 0.00 s, elapsed: 0.06 s

For a file_fdw, the output will look like:

analyze (verbose) pglog;
INFO:  analyzing "public.pglog"
INFO:  analyze of table "postgres.public.pglog"
tuples: 30000 tuples in samples, 60042 estimated total tuples
avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
buffer usage: 182 hits, 0 reads, 0 dirtied
WAL usage: 118 records, 0 full page images, 13086 bytes
system usage: CPU: user: 0.40 s, system: 0.00 s, elapsed: 0.41 s

I've also slightly modified 0002 to display "automatic analyze" when
we're inside an autovacuum worker, similar to what's done with vacuum
output.

Regards,
Anthonin

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Masahiko Sawada
Date:
On Wed, Jul 24, 2024 at 1:58 AM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
>
> On Mon, Jul 22, 2024 at 10:59 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > The first line would vary depending on whether an autovacuum worker or
> > not. And the above suggestion includes a change of term "row" to
> > "tuple" for better consistency with VACUUM VERBOSE outputs. I think it
> > would be great if autoanalyze also writes logs in the same format.
> > IIUC with the patch, autoanalyze logs don't include the page and tuple
> > statistics.
>
> One issue is that the number of scanned pages, live tuples and dead
> tuples is only available in acquire_sample_rows which is where the log
> containing those stats is emitted. I've tried to implement the
> following in 0003:
> - Sampling functions now accept an AcquireSampleStats struct to store
> pages and tuples stats
> - Log is removed from sampling functions
> - do_analyze_rel now outputs scanned and tuples statistics when
> relevant. sampling from fdw doesn't provide those statistics so they
> are not displayed in those cases.

Studying how we write verbose log messages, it seems that currently
ANALYZE (autoanalyze) lets tables and FDWs write logs in its own
format. Which makes sense to me as some instruments for heap such as
dead tuple might not be necessary for FDWs and FDW might want to write
other information such as executed queries. An alternative idea would
be to pass StringInfo to AcquireSampleRowsFunc() so that callback can
write its messages there. This is somewhat similar to what we do in
the EXPLAIN command (cf, ExplainPropertyText() etc). It could be too
much but I think it could be better than writing logs in the single
format.

>
> I've also slightly modified 0002 to display "automatic analyze" when
> we're inside an autovacuum worker, similar to what's done with vacuum
> output.

+1

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
On Sat, Jul 27, 2024 at 12:35 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> An alternative idea would
> be to pass StringInfo to AcquireSampleRowsFunc() so that callback can
> write its messages there. This is somewhat similar to what we do in
> the EXPLAIN command (cf, ExplainPropertyText() etc). It could be too
> much but I think it could be better than writing logs in the single
> format.

I've tested this approach, it definitely looks better. I've added a
logbuf StringInfo to AcquireSampleRowsFunc which will receive the
logs. elevel was removed as it is not used anymore. Since everything
is in the same log line, I've removed the relation name in the acquire
sample functions.

For partitioned tables, I've also added the processed partition table
being sampled. The output will look like:

INFO:  analyze of table "postgres.public.test_partition"
Sampling rows from child "public.test_partition_1"
pages: 5 of 5 scanned
tuples: 999 live tuples, 0 are dead; 999 tuples in sample, 999
estimated total tuples
Sampling rows from child "public.test_partition_2"
pages: 5 of 5 scanned
tuples: 1000 live tuples, 0 are dead; 1000 tuples in sample, 1000
estimated total tuples
avg read rate: 2.604 MB/s, avg write rate: 0.000 MB/s
...

For a file_fdw, the output will be:

INFO:  analyze of table "postgres.public.pglog"
tuples: 60043 tuples; 30000 tuples in sample
avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
...

Regards,
Anthonin

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Masahiko Sawada
Date:
Hi,

On Mon, Jul 29, 2024 at 12:12 AM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
>
> On Sat, Jul 27, 2024 at 12:35 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > An alternative idea would
> > be to pass StringInfo to AcquireSampleRowsFunc() so that callback can
> > write its messages there. This is somewhat similar to what we do in
> > the EXPLAIN command (cf, ExplainPropertyText() etc). It could be too
> > much but I think it could be better than writing logs in the single
> > format.
>

I have one comment on 0001 patch:

                         /*
                          * Calculate the difference in the Page
Hit/Miss/Dirty that
                          * happened as part of the analyze by
subtracting out the
                          * pre-analyze values which we saved above.
                          */
-                        AnalyzePageHit = VacuumPageHit - AnalyzePageHit;
-                        AnalyzePageMiss = VacuumPageMiss - AnalyzePageMiss;
-                        AnalyzePageDirty = VacuumPageDirty - AnalyzePageDirty;
+                        memset(&bufferusage, 0, sizeof(BufferUsage));
+                        BufferUsageAccumDiff(&bufferusage,
&pgBufferUsage, &startbufferusage);
+
+                        total_blks_hit = bufferusage.shared_blks_hit +
+                                bufferusage.local_blks_hit;
+                        total_blks_read = bufferusage.shared_blks_read +
+                                bufferusage.local_blks_read;
+                        total_blks_dirtied = bufferusage.shared_blks_dirtied +
+                                bufferusage.local_blks_dirtied;

The comment should also be updated or removed.

And here are some comments on 0002 patch:

-           TimestampDifference(starttime, endtime, &secs_dur, &usecs_dur);
+           delay_in_ms = TimestampDifferenceMilliseconds(starttime, endtime);

I think that this change is to make vacuum code consistent with
analyze code, particularly the following part:

            /*
             * We do not expect an analyze to take > 25 days and it simplifies
             * things a bit to use TimestampDifferenceMilliseconds.
             */
            delay_in_ms = TimestampDifferenceMilliseconds(starttime, endtime);

However, as the above comment says, delay_in_ms can have a duration up
to 25 days. I guess it would not be a problem for analyze cases but
could be in vacuum cases as vacuum could sometimes be running for a
very long time. I've seen vacuums running even for almost 1 month. So
I think we should keep this part.

---
         /* measure elapsed time iff autovacuum logging requires it */
-        if (AmAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
+        if (instrument)

The comment should also be updated.

---
Could you split the 0002 patch into two patches? One is to have
ANALYZE command (with VERBOSE option) write the buffer usage, and
second one is to add WAL usage to both ANALYZE command and
autoanalyze. I think adding WAL usage to ANALYZE could be
controversial as it should not be WAL-intensive operation, so I'd like
to keep them separate.


> I've tested this approach, it definitely looks better. I've added a
> logbuf StringInfo to AcquireSampleRowsFunc which will receive the
> logs. elevel was removed as it is not used anymore. Since everything
> is in the same log line, I've removed the relation name in the acquire
> sample functions.
>
> For partitioned tables, I've also added the processed partition table
> being sampled. The output will look like:
>
> INFO:  analyze of table "postgres.public.test_partition"
> Sampling rows from child "public.test_partition_1"
> pages: 5 of 5 scanned
> tuples: 999 live tuples, 0 are dead; 999 tuples in sample, 999
> estimated total tuples
> Sampling rows from child "public.test_partition_2"
> pages: 5 of 5 scanned
> tuples: 1000 live tuples, 0 are dead; 1000 tuples in sample, 1000
> estimated total tuples
> avg read rate: 2.604 MB/s, avg write rate: 0.000 MB/s
> ...
>
> For a file_fdw, the output will be:
>
> INFO:  analyze of table "postgres.public.pglog"
> tuples: 60043 tuples; 30000 tuples in sample
> avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
> ...

Thank you for updating the patch. With your patch, I got the following
logs for when executing ANALYZE VERBOSE on a partitioned table:

postgres(1:3971560)=# analyze (verbose) p;
INFO:  analyzing "public.p" inheritance tree
INFO:  analyze of table "postgres.public.p"
Sampling rows from child "public.c1"
pages: 10000 of 14750 scanned
tuples: 2259833 live tuples, 0 are dead; 10000 tuples in sample,
3333254 estimated total tuples
Sampling rows from child "public.c2"
pages: 10000 of 14750 scanned
tuples: 2260000 live tuples, 0 are dead; 10000 tuples in sample,
3333500 estimated total tuples
Sampling rows from child "public.c3"
pages: 10000 of 14750 scanned
tuples: 2259833 live tuples, 0 are dead; 10000 tuples in sample,
3333254 estimated total tuples
avg read rate: 335.184 MB/s, avg write rate: 0.031 MB/s
buffer usage: 8249 hits, 21795 reads, 2 dirtied
WAL usage: 6 records, 1 full page images, 8825 bytes
system usage: CPU: user: 0.46 s, system: 0.03 s, elapsed: 0.50 s
:

Whereas the current log messages are like follow:

INFO:  analyzing "public.p" inheritance tree
INFO:  "c1": scanned 10000 of 14750 pages, containing 2259833 live
rows and 0 dead rows; 10000 rows in sample, 3333254 estimated total
rows
INFO:  "c2": scanned 10000 of 14750 pages, containing 2259834 live
rows and 0 dead rows; 10000 rows in sample, 3333255 estimated total
rows
INFO:  "c3": scanned 10000 of 14750 pages, containing 2259833 live
rows and 0 dead rows; 10000 rows in sample, 3333254 estimated total
rows
:

It seems to me that the current style is more concise and readable (3
rows per table vs. 1 row per table). We might need to consider a
better output format for partitioned tables as the number of
partitions could be high. I don't have a good idea now, though.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
Hi,

On Tue, Jul 30, 2024 at 1:13 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> I have one comment on 0001 patch:
> The comment should also be updated or removed.

Ok, I've removed the comment.

> However, as the above comment says, delay_in_ms can have a duration up
> to 25 days. I guess it would not be a problem for analyze cases but
> could be in vacuum cases as vacuum could sometimes be running for a
> very long time. I've seen vacuums running even for almost 1 month. So
> I think we should keep this part.

Good point, I've reverted to using TimestampDifference for vacuum.

>          /* measure elapsed time iff autovacuum logging requires it */
> -        if (AmAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
> +        if (instrument)
>
> The comment should also be updated.

Updated.

> Could you split the 0002 patch into two patches? One is to have
> ANALYZE command (with VERBOSE option) write the buffer usage, and
> second one is to add WAL usage to both ANALYZE command and
> autoanalyze. I think adding WAL usage to ANALYZE could be
> controversial as it should not be WAL-intensive operation, so I'd like
> to keep them separate.

I've split the patch, 0002 makes verbose outputs the same as
autoanalyze logs with buffer/io/system while 0003 adds WAL usage
output.

> It seems to me that the current style is more concise and readable (3
> rows per table vs. 1 row per table). We might need to consider a
> better output format for partitioned tables as the number of
> partitions could be high. I don't have a good idea now, though.

A possible change would be to pass an inh flag when an acquirefunc is
called from acquire_inherited_sample_rows. The acquirefunc could then
use an alternative log format to append to logbuf. This way, we could
have a more compact format for partitioned tables.

Regards,
Anthonin

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
On Tue, Jul 30, 2024 at 9:21 AM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
> A possible change would be to pass an inh flag when an acquirefunc is
> called from acquire_inherited_sample_rows. The acquirefunc could then
> use an alternative log format to append to logbuf. This way, we could
> have a more compact format for partitioned tables.

I've just tested this, the result isn't great as it creates an
inconsistent output

INFO:  analyze of table "postgres.public.test_partition"
"test_partition_1": scanned 5 of 5 pages, containing 999 live tuples
and 0 dead tuples; 999 rows in sample, 999 estimated total rows
"test_partition_2": scanned 5 of 5 pages, containing 1000 live tuples
and 0 dead tuples; 1000 rows in sample, 1000 estimated total rows
avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
...
INFO:  analyze of table "postgres.public.test_partition_1"
pages: 5 of 5 scanned
tuples: 999 live tuples, 0 are dead; 999 tuples in sample, 999
estimated total tuples
avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s

Maybe the best approach is to always use the compact form?

INFO:  analyze of table "postgres.public.test_partition"
"test_partition_1": scanned 5 of 5 pages, containing 999 live tuples
and 0 dead tuples; 999 tuples in sample, 999 estimated total tuples
"test_partition_2": scanned 5 of 5 pages, containing 1000 live tuples
and 0 dead tuples; 1000 tuples in sample, 1000 estimated total tuples
avg read rate: 1.953 MB/s, avg write rate: 0.000 MB/s
...
INFO:  analyze of table "postgres.public.test_partition_1"
"test_partition_1": scanned 5 of 5 pages, containing 999 live tuples
and 0 dead tuples; 999 tuples in sample, 999 estimated total tuples
avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s

I've updated the patchset with those changes. 0004 introduces the
StringInfo logbuf so we can output logs as a single log and during
ANALYZE VERBOSE while using the compact form.

Regards,
Anthonin

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Masahiko Sawada
Date:
On Wed, Jul 31, 2024 at 12:03 AM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
>
> On Tue, Jul 30, 2024 at 9:21 AM Anthonin Bonnefoy
> <anthonin.bonnefoy@datadoghq.com> wrote:
> > A possible change would be to pass an inh flag when an acquirefunc is
> > called from acquire_inherited_sample_rows. The acquirefunc could then
> > use an alternative log format to append to logbuf. This way, we could
> > have a more compact format for partitioned tables.
>
> I've just tested this, the result isn't great as it creates an
> inconsistent output
>
> INFO:  analyze of table "postgres.public.test_partition"
> "test_partition_1": scanned 5 of 5 pages, containing 999 live tuples
> and 0 dead tuples; 999 rows in sample, 999 estimated total rows
> "test_partition_2": scanned 5 of 5 pages, containing 1000 live tuples
> and 0 dead tuples; 1000 rows in sample, 1000 estimated total rows
> avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
> ...
> INFO:  analyze of table "postgres.public.test_partition_1"
> pages: 5 of 5 scanned
> tuples: 999 live tuples, 0 are dead; 999 tuples in sample, 999
> estimated total tuples
> avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
>
> Maybe the best approach is to always use the compact form?
>
> INFO:  analyze of table "postgres.public.test_partition"
> "test_partition_1": scanned 5 of 5 pages, containing 999 live tuples
> and 0 dead tuples; 999 tuples in sample, 999 estimated total tuples
> "test_partition_2": scanned 5 of 5 pages, containing 1000 live tuples
> and 0 dead tuples; 1000 tuples in sample, 1000 estimated total tuples
> avg read rate: 1.953 MB/s, avg write rate: 0.000 MB/s
> ...
> INFO:  analyze of table "postgres.public.test_partition_1"
> "test_partition_1": scanned 5 of 5 pages, containing 999 live tuples
> and 0 dead tuples; 999 tuples in sample, 999 estimated total tuples
> avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
>
> I've updated the patchset with those changes. 0004 introduces the
> StringInfo logbuf so we can output logs as a single log and during
> ANALYZE VERBOSE while using the compact form.
>

Fair point. I'll consider a better output format.

Meanwhile, I think we can push 0001 and 0002 patches since they are in
good shape. I've updated commit messages to them and slightly changed
0002 patch to write "finished analyzing of table \"%s.%s.%s\" instead
of  "analyze of table \"%s.%s.%s\".

Also, regarding 0003 patch, what is the main reason why we want to add
WAL usage to analyze reports? I think that analyze normally does not
write WAL records much so I'm not sure it's going to provide a good
insight for users.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

Attachment

Re: Use pgBufferUsage for block reporting in analyze

From
Anthonin Bonnefoy
Date:
On Wed, Jul 31, 2024 at 9:36 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> Meanwhile, I think we can push 0001 and 0002 patches since they are in
> good shape. I've updated commit messages to them and slightly changed
> 0002 patch to write "finished analyzing of table \"%s.%s.%s\" instead
> of  "analyze of table \"%s.%s.%s\".

Wouldn't it make sense to do the same for autoanalyze and write
"finished automatic analyze of table \"%s.%s.%s\"\n" instead of
"automatic analyze of table \"%s.%s.%s\"\n"?

> Also, regarding 0003 patch, what is the main reason why we want to add
> WAL usage to analyze reports? I think that analyze normally does not
> write WAL records much so I'm not sure it's going to provide a good
> insight for users.

There was no strong reason except for consistency with VACUUM VERBOSE
output. But as you said, it's not really providing valuable
information so it's probably better to keep the noise down and drop
it.

Regards,
Anthonin Bonnefoy



Re: Use pgBufferUsage for block reporting in analyze

From
Masahiko Sawada
Date:
On Wed, Jul 31, 2024 at 11:27 PM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
>
> On Wed, Jul 31, 2024 at 9:36 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > Meanwhile, I think we can push 0001 and 0002 patches since they are in
> > good shape. I've updated commit messages to them and slightly changed
> > 0002 patch to write "finished analyzing of table \"%s.%s.%s\" instead
> > of  "analyze of table \"%s.%s.%s\".
>
> Wouldn't it make sense to do the same for autoanalyze and write
> "finished automatic analyze of table \"%s.%s.%s\"\n" instead of
> "automatic analyze of table \"%s.%s.%s\"\n"?

I think that the current style is consistent with autovacuum logs:

2024-08-01 16:04:48.088 PDT [12302] LOG:  automatic vacuum of table
"postgres.public.test": index scans: 0
        pages: 0 removed, 443 remain, 443 scanned (100.00% of total)
        tuples: 0 removed, 100000 remain, 0 are dead but not yet removable
        removable cutoff: 751, which was 0 XIDs old when operation ended
        new relfrozenxid: 739, which is 1 XIDs ahead of previous value
        frozen: 0 pages from table (0.00% of total) had 0 tuples frozen
        index scan not needed: 0 pages from table (0.00% of total) had
0 dead item identifiers removed
        avg read rate: 0.000 MB/s, avg write rate: 1.466 MB/s
        buffer usage: 905 hits, 0 reads, 4 dirtied
        system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.02 s
2024-08-01 16:04:48.125 PDT [12302] LOG:  automatic analyze of table
"postgres.public.test"
        avg read rate: 5.551 MB/s, avg write rate: 0.617 MB/s
        buffer usage: 512 hits, 27 reads, 3 dirtied
        system usage: CPU: user: 0.02 s, system: 0.00 s, elapsed: 0.03 s

Since ANALYZE command writes the start log, I think it makes sense to
write "finished" at the end of the operation:

=# analyze verbose test;
INFO:  analyzing "public.test"
INFO:  "test": scanned 443 of 443 pages, containing 100000 live rows
and 0 dead rows; 30000 rows in sample, 100000 estimated total rows
INFO:  finished analyzing table "postgres.public.test"
avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
buffer usage: 549 hits, 0 reads, 0 dirtied
system usage: CPU: user: 0.02 s, system: 0.00 s, elapsed: 0.03 s
ANALYZE

>
> > Also, regarding 0003 patch, what is the main reason why we want to add
> > WAL usage to analyze reports? I think that analyze normally does not
> > write WAL records much so I'm not sure it's going to provide a good
> > insight for users.
>
> There was no strong reason except for consistency with VACUUM VERBOSE
> output. But as you said, it's not really providing valuable
> information so it's probably better to keep the noise down and drop
> it.

Okay. I think writing WAL usage would not be very noisy and probably
could help some cases where (auto)analyze unexpectedly writes many WAL
records (e.g., writing full page images much), and is consistent with
(auto)vacuum logs as you mentioned. So let's go with this direction
unless others think differently.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com



Re: Use pgBufferUsage for block reporting in analyze

From
Masahiko Sawada
Date:
On Fri, Aug 2, 2024 at 8:11 AM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
>
> On Wed, Jul 31, 2024 at 11:27 PM Anthonin Bonnefoy
> <anthonin.bonnefoy@datadoghq.com> wrote:
> >
> > On Wed, Jul 31, 2024 at 9:36 PM Masahiko Sawada <sawada.mshk@gmail.com> wrote:
> > > Meanwhile, I think we can push 0001 and 0002 patches since they are in
> > > good shape. I've updated commit messages to them and slightly changed
> > > 0002 patch to write "finished analyzing of table \"%s.%s.%s\" instead
> > > of  "analyze of table \"%s.%s.%s\".
> >
> > Wouldn't it make sense to do the same for autoanalyze and write
> > "finished automatic analyze of table \"%s.%s.%s\"\n" instead of
> > "automatic analyze of table \"%s.%s.%s\"\n"?
>
> I think that the current style is consistent with autovacuum logs:
>
> 2024-08-01 16:04:48.088 PDT [12302] LOG:  automatic vacuum of table
> "postgres.public.test": index scans: 0
>         pages: 0 removed, 443 remain, 443 scanned (100.00% of total)
>         tuples: 0 removed, 100000 remain, 0 are dead but not yet removable
>         removable cutoff: 751, which was 0 XIDs old when operation ended
>         new relfrozenxid: 739, which is 1 XIDs ahead of previous value
>         frozen: 0 pages from table (0.00% of total) had 0 tuples frozen
>         index scan not needed: 0 pages from table (0.00% of total) had
> 0 dead item identifiers removed
>         avg read rate: 0.000 MB/s, avg write rate: 1.466 MB/s
>         buffer usage: 905 hits, 0 reads, 4 dirtied
>         system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.02 s
> 2024-08-01 16:04:48.125 PDT [12302] LOG:  automatic analyze of table
> "postgres.public.test"
>         avg read rate: 5.551 MB/s, avg write rate: 0.617 MB/s
>         buffer usage: 512 hits, 27 reads, 3 dirtied
>         system usage: CPU: user: 0.02 s, system: 0.00 s, elapsed: 0.03 s
>
> Since ANALYZE command writes the start log, I think it makes sense to
> write "finished" at the end of the operation:
>
> =# analyze verbose test;
> INFO:  analyzing "public.test"
> INFO:  "test": scanned 443 of 443 pages, containing 100000 live rows
> and 0 dead rows; 30000 rows in sample, 100000 estimated total rows
> INFO:  finished analyzing table "postgres.public.test"
> avg read rate: 0.000 MB/s, avg write rate: 0.000 MB/s
> buffer usage: 549 hits, 0 reads, 0 dirtied
> system usage: CPU: user: 0.02 s, system: 0.00 s, elapsed: 0.03 s
> ANALYZE
>

Committed 0001 and 0002 patches.

> >
> > > Also, regarding 0003 patch, what is the main reason why we want to add
> > > WAL usage to analyze reports? I think that analyze normally does not
> > > write WAL records much so I'm not sure it's going to provide a good
> > > insight for users.
> >
> > There was no strong reason except for consistency with VACUUM VERBOSE
> > output. But as you said, it's not really providing valuable
> > information so it's probably better to keep the noise down and drop
> > it.
>
> Okay. I think writing WAL usage would not be very noisy and probably
> could help some cases where (auto)analyze unexpectedly writes many WAL
> records (e.g., writing full page images much), and is consistent with
> (auto)vacuum logs as you mentioned. So let's go with this direction
> unless others think differently.

I've updated the patch to add WAL usage to analyze. I'm going to push
it this week, barring any objections.

Regards,

--
Masahiko Sawada
Amazon Web Services: https://aws.amazon.com

Attachment