Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbdd5726

Browse files
committed
Add the capability to display summary statistics to pg_xlogdump.
The new --stats/--stats=record options to pg_xlogdump display perrmgr/per record statistics about the parsed WAL. This is useful tounderstand what the WAL primarily consists of, to allow targetedoptimizations on application, configuration, and core code level.It is likely that we will want to fine tune the statistics further,but the feature already is quite helpful.Author: Abhijit Menon-Sen, slightly editorialized by meReviewed-By: Andres Freund, Dilip Kumar and Furuya OsamuDiscussion: 20140604104716.GA3989@toroid.org
1 parent728f152 commitbdd5726

File tree

2 files changed

+237
-12
lines changed

2 files changed

+237
-12
lines changed

‎contrib/pg_xlogdump/pg_xlogdump.c

Lines changed: 225 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,31 @@ typedef struct XLogDumpConfig
4141
intstop_after_records;
4242
intalready_displayed_records;
4343
boolfollow;
44+
boolstats;
45+
boolstats_per_record;
4446

4547
/* filter options */
4648
intfilter_by_rmgr;
4749
TransactionIdfilter_by_xid;
4850
boolfilter_by_xid_enabled;
4951
}XLogDumpConfig;
5052

53+
typedefstructStats
54+
{
55+
uint64count;
56+
uint64rec_len;
57+
uint64fpi_len;
58+
}Stats;
59+
60+
#defineMAX_XLINFO_TYPES 16
61+
62+
typedefstructXLogDumpStats
63+
{
64+
uint64count;
65+
Statsrmgr_stats[RM_NEXT_ID];
66+
Statsrecord_stats[RM_NEXT_ID][MAX_XLINFO_TYPES];
67+
}XLogDumpStats;
68+
5169
staticvoid
5270
fatal_error(constchar*fmt,...)
5371
__attribute__((format(PG_PRINTF_ATTRIBUTE,1,2)));
@@ -322,22 +340,49 @@ XLogDumpReadPage(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen,
322340
}
323341

324342
/*
325-
*Print arecordto stdout
343+
*Store per-rmgr and per-recordstatistics for a given record.
326344
*/
327345
staticvoid
328-
XLogDumpDisplayRecord(XLogDumpConfig*config,XLogRecPtrReadRecPtr,XLogRecord*record)
346+
XLogDumpCountRecord(XLogDumpConfig*config,XLogDumpStats*stats,XLogRecPtrReadRecPtr,XLogRecord*record)
329347
{
330-
constRmgrDescData*desc=&RmgrDescTable[record->xl_rmid];
348+
RmgrIdrmid;
349+
uint8recid;
350+
351+
stats->count++;
331352

332-
if (config->filter_by_rmgr!=-1&&
333-
config->filter_by_rmgr!=record->xl_rmid)
334-
return;
353+
/* Update per-rmgr statistics */
335354

336-
if (config->filter_by_xid_enabled&&
337-
config->filter_by_xid!=record->xl_xid)
338-
return;
355+
rmid=record->xl_rmid;
339356

340-
config->already_displayed_records++;
357+
stats->rmgr_stats[rmid].count++;
358+
stats->rmgr_stats[rmid].rec_len+=
359+
record->xl_len+SizeOfXLogRecord;
360+
stats->rmgr_stats[rmid].fpi_len+=
361+
record->xl_tot_len- (record->xl_len+SizeOfXLogRecord);
362+
363+
/*
364+
* Update per-record statistics, where the record is identified by a
365+
* combination of the RmgrId and the four bits of the xl_info field
366+
* that are the rmgr's domain (resulting in sixteen possible entries
367+
* per RmgrId).
368+
*/
369+
370+
recid=record->xl_info >>4;
371+
372+
stats->record_stats[rmid][recid].count++;
373+
stats->record_stats[rmid][recid].rec_len+=
374+
record->xl_len+SizeOfXLogRecord;
375+
stats->record_stats[rmid][recid].fpi_len+=
376+
record->xl_tot_len- (record->xl_len+SizeOfXLogRecord);
377+
}
378+
379+
/*
380+
* Print a record to stdout
381+
*/
382+
staticvoid
383+
XLogDumpDisplayRecord(XLogDumpConfig*config,XLogRecPtrReadRecPtr,XLogRecord*record)
384+
{
385+
constRmgrDescData*desc=&RmgrDescTable[record->xl_rmid];
341386

342387
printf("rmgr: %-11s len (rec/tot): %6u/%6u, tx: %10u, lsn: %X/%08X, prev %X/%08X, bkp: %u%u%u%u, desc: %s ",
343388
desc->rm_name,
@@ -381,6 +426,134 @@ XLogDumpDisplayRecord(XLogDumpConfig *config, XLogRecPtr ReadRecPtr, XLogRecord
381426
}
382427
}
383428

429+
/*
430+
* Display a single row of record counts and sizes for an rmgr or record.
431+
*/
432+
staticvoid
433+
XLogDumpStatsRow(constchar*name,
434+
uint64n,doublen_pct,
435+
uint64rec_len,doublerec_len_pct,
436+
uint64fpi_len,doublefpi_len_pct,
437+
uint64total_len,doubletotal_len_pct)
438+
{
439+
printf("%-27s "
440+
"%20"INT64_MODIFIER"u (%6.02f) "
441+
"%20"INT64_MODIFIER"u (%6.02f) "
442+
"%20"INT64_MODIFIER"u (%6.02f) "
443+
"%20"INT64_MODIFIER"u (%6.02f)\n",
444+
name,n,n_pct,rec_len,rec_len_pct,fpi_len,fpi_len_pct,
445+
total_len,total_len_pct);
446+
}
447+
448+
449+
/*
450+
* Display summary statistics about the records seen so far.
451+
*/
452+
staticvoid
453+
XLogDumpDisplayStats(XLogDumpConfig*config,XLogDumpStats*stats)
454+
{
455+
intri,rj;
456+
uint64total_count=0;
457+
uint64total_rec_len=0;
458+
uint64total_fpi_len=0;
459+
uint64total_len=0;
460+
461+
/* ---
462+
* Make a first pass to calculate column totals:
463+
* count(*),
464+
* sum(xl_len+SizeOfXLogRecord),
465+
* sum(xl_tot_len-xl_len-SizeOfXLogRecord), and
466+
* sum(xl_tot_len).
467+
* These are used to calculate percentages for each record type.
468+
* ---
469+
*/
470+
471+
for (ri=0;ri<RM_NEXT_ID;ri++)
472+
{
473+
total_count+=stats->rmgr_stats[ri].count;
474+
total_rec_len+=stats->rmgr_stats[ri].rec_len;
475+
total_fpi_len+=stats->rmgr_stats[ri].fpi_len;
476+
}
477+
total_len=total_rec_len+total_fpi_len;
478+
479+
/*
480+
* 27 is strlen("Transaction/COMMIT_PREPARED"),
481+
* 20 is strlen(2^64), 8 is strlen("(100.00%)")
482+
*/
483+
484+
printf("%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n"
485+
"%-27s %20s %8s %20s %8s %20s %8s %20s %8s\n",
486+
"Type","N","(%)","Record size","(%)","FPI size","(%)","Combined size","(%)",
487+
"----","-","---","-----------","---","--------","---","-------------","---");
488+
489+
for (ri=0;ri<RM_NEXT_ID;ri++)
490+
{
491+
uint64count,rec_len,fpi_len,tot_len;
492+
constRmgrDescData*desc=&RmgrDescTable[ri];
493+
494+
if (!config->stats_per_record)
495+
{
496+
count=stats->rmgr_stats[ri].count;
497+
rec_len=stats->rmgr_stats[ri].rec_len;
498+
fpi_len=stats->rmgr_stats[ri].fpi_len;
499+
tot_len=rec_len+fpi_len;
500+
501+
XLogDumpStatsRow(desc->rm_name,
502+
count,100* (double)count /total_count,
503+
rec_len,100* (double)rec_len /total_rec_len,
504+
fpi_len,100* (double)fpi_len /total_fpi_len,
505+
tot_len,100* (double)tot_len /total_len);
506+
}
507+
else
508+
{
509+
for (rj=0;rj<MAX_XLINFO_TYPES;rj++)
510+
{
511+
constchar*id;
512+
513+
count=stats->record_stats[ri][rj].count;
514+
rec_len=stats->record_stats[ri][rj].rec_len;
515+
fpi_len=stats->record_stats[ri][rj].fpi_len;
516+
tot_len=rec_len+fpi_len;
517+
518+
/* Skip undefined combinations and ones that didn't occur */
519+
if (count==0)
520+
continue;
521+
522+
/* the upper four bits in xl_info are the rmgr's */
523+
id=desc->rm_identify(rj <<4);
524+
if (id==NULL)
525+
id=psprintf("UNKNOWN (%x)",rj <<4);
526+
527+
XLogDumpStatsRow(psprintf("%s/%s",desc->rm_name,id),
528+
count,100* (double)count /total_count,
529+
rec_len,100* (double)rec_len /total_rec_len,
530+
fpi_len,100* (double)fpi_len /total_fpi_len,
531+
tot_len,100* (double)tot_len /total_len);
532+
}
533+
}
534+
}
535+
536+
printf("%-27s %20s %8s %20s %8s %20s %8s %20s\n",
537+
"","--------","","--------","","--------","","--------");
538+
539+
/*
540+
* The percentages in earlier rows were calculated against the
541+
* column total, but the ones that follow are against the row total.
542+
* Note that these are displayed with a % symbol to differentiate
543+
* them from the earlier ones, and are thus up to 9 characters long.
544+
*/
545+
546+
printf("%-27s "
547+
"%20"INT64_MODIFIER"u %-9s"
548+
"%20"INT64_MODIFIER"u %-9s"
549+
"%20"INT64_MODIFIER"u %-9s"
550+
"%20"INT64_MODIFIER"u %-6s\n",
551+
"Total",stats->count,"",
552+
total_rec_len,psprintf("[%.02f%%]",100* (double)total_rec_len /total_len),
553+
total_fpi_len,psprintf("[%.02f%%]",100* (double)total_fpi_len /total_len),
554+
total_len,"[100%]");
555+
}
556+
384557
staticvoid
385558
usage(void)
386559
{
@@ -402,6 +575,8 @@ usage(void)
402575
printf(" (default: 1 or the value used in STARTSEG)\n");
403576
printf(" -V, --version output version information, then exit\n");
404577
printf(" -x, --xid=XID only show records with TransactionId XID\n");
578+
printf(" -z, --stats[=record] show statistics instead of records\n");
579+
printf(" (optionally, show per-record statistics)\n");
405580
printf(" -?, --help show this help, then exit\n");
406581
}
407582

@@ -413,6 +588,7 @@ main(int argc, char **argv)
413588
XLogReaderState*xlogreader_state;
414589
XLogDumpPrivateprivate;
415590
XLogDumpConfigconfig;
591+
XLogDumpStatsstats;
416592
XLogRecord*record;
417593
XLogRecPtrfirst_record;
418594
char*errormsg;
@@ -429,6 +605,7 @@ main(int argc, char **argv)
429605
{"timeline",required_argument,NULL,'t'},
430606
{"xid",required_argument,NULL,'x'},
431607
{"version",no_argument,NULL,'V'},
608+
{"stats",optional_argument,NULL,'z'},
432609
{NULL,0,NULL,0}
433610
};
434611

@@ -439,6 +616,7 @@ main(int argc, char **argv)
439616

440617
memset(&private,0,sizeof(XLogDumpPrivate));
441618
memset(&config,0,sizeof(XLogDumpConfig));
619+
memset(&stats,0,sizeof(XLogDumpStats));
442620

443621
private.timeline=1;
444622
private.startptr=InvalidXLogRecPtr;
@@ -452,14 +630,16 @@ main(int argc, char **argv)
452630
config.filter_by_rmgr=-1;
453631
config.filter_by_xid=InvalidTransactionId;
454632
config.filter_by_xid_enabled= false;
633+
config.stats= false;
634+
config.stats_per_record= false;
455635

456636
if (argc <=1)
457637
{
458638
fprintf(stderr,"%s: no arguments specified\n",progname);
459639
gotobad_argument;
460640
}
461641

462-
while ((option=getopt_long(argc,argv,"be:?fn:p:r:s:t:Vx:",
642+
while ((option=getopt_long(argc,argv,"be:?fn:p:r:s:t:Vx:z",
463643
long_options,&optindex))!=-1)
464644
{
465645
switch (option)
@@ -552,6 +732,21 @@ main(int argc, char **argv)
552732
}
553733
config.filter_by_xid_enabled= true;
554734
break;
735+
case'z':
736+
config.stats= true;
737+
config.stats_per_record= false;
738+
if (optarg)
739+
{
740+
if (strcmp(optarg,"record")==0)
741+
config.stats_per_record= true;
742+
elseif (strcmp(optarg,"rmgr")!=0)
743+
{
744+
fprintf(stderr,"%s: unrecognised argument to --stats: %s\n",
745+
progname,optarg);
746+
gotobad_argument;
747+
}
748+
}
749+
break;
555750
default:
556751
gotobad_argument;
557752
}
@@ -712,14 +907,32 @@ main(int argc, char **argv)
712907

713908
/* after reading the first record, continue at next one */
714909
first_record=InvalidXLogRecPtr;
715-
XLogDumpDisplayRecord(&config,xlogreader_state->ReadRecPtr,record);
910+
911+
/* apply all specified filters */
912+
if (config.filter_by_rmgr!=-1&&
913+
config.filter_by_rmgr!=record->xl_rmid)
914+
continue;
915+
916+
if (config.filter_by_xid_enabled&&
917+
config.filter_by_xid!=record->xl_xid)
918+
continue;
919+
920+
/* process the record */
921+
if (config.stats== true)
922+
XLogDumpCountRecord(&config,&stats,xlogreader_state->ReadRecPtr,record);
923+
else
924+
XLogDumpDisplayRecord(&config,xlogreader_state->ReadRecPtr,record);
716925

717926
/* check whether we printed enough */
927+
config.already_displayed_records++;
718928
if (config.stop_after_records>0&&
719929
config.already_displayed_records >=config.stop_after_records)
720930
break;
721931
}
722932

933+
if (config.stats== true)
934+
XLogDumpDisplayStats(&config,&stats);
935+
723936
if (errormsg)
724937
fatal_error("error in WAL record at %X/%X: %s\n",
725938
(uint32) (xlogreader_state->ReadRecPtr >>32),

‎doc/src/sgml/pg_xlogdump.sgml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,18 @@ PostgreSQL documentation
179179
</listitem>
180180
</varlistentry>
181181

182+
<varlistentry>
183+
<term><option>-z</option></term>
184+
<term><option>--stats[=record]</option></term>
185+
<listitem>
186+
<para>
187+
Display summary statistics (number and size of records and
188+
full-page images) instead of individual records. Optionally
189+
generate statistics per-record instead of per-rmgr.
190+
</para>
191+
</listitem>
192+
</varlistentry>
193+
182194
<varlistentry>
183195
<term><option>-?</></term>
184196
<term><option>--help</></term>

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp