Reduce to overview

Print only a single line per table (and schema and database) containing
the total size, the size of the table(s) proper and the size of the
indexes.

Also print this to an index.html file in the given directory instead of
stdout. This gives us a chance to print per table detail pages later, if
required.
This commit is contained in:
Peter J. Holzer 2016-03-08 10:24:02 +01:00
parent 0f5b9262ff
commit ed7ae3b2c5
1 changed files with 78 additions and 74 deletions

View File

@ -3,98 +3,85 @@ use charnames ':full'; # only necessary before v5.16
use strict;
use v5.10;
use warnings;
use autodie;
use experimental qw(autoderef);
use DBIx::SimpleConnect;
use Encode qw(:fallbacks encode);
use Getopt::Long;
use Pod::Usage;
my $db = "default";
my $dir = ".";
GetOptions(
'dbname=s' => \$db,
'directory=s' => \$dir,
) or pod2usage(1);
binmode STDOUT, ":encoding(UTF-8)";
my $db = shift // "default";
{
no autodie;
unless (chdir($dir)) {
# if at first we don't succeed ...
mkdir $dir or die "cannot create $dir: $!";
chdir $dir or die "cannot chdir to $dir: $!";
}
}
my $dbh = DBIx::SimpleConnect->connect($db, {RaiseError => 1});
my $table_usage
= $dbh->selectall_arrayref("
select schemaname,
tablename,
pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename)) as s
my $overview
= $dbh->selectall_hashref("
select schemaname, tablename,
sum(pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(tablename))) as total_size,
sum(pg_table_size(quote_ident(schemaname) || '.' || quote_ident(tablename))) as table_size,
sum(pg_indexes_size(quote_ident(schemaname) || '.' || quote_ident(tablename))) as indexes_size
from pg_tables
group by rollup (schemaname, tablename)
",
{ Slice => {} }
['schemaname', 'tablename']
);
my $du;
for my $tu (@$table_usage) {
$du->{$tu->{schemaname}}{".s"} += $tu->{s};
$du->{$tu->{schemaname}}{$tu->{tablename}}{".s"} += $tu->{s};
$du->{$tu->{schemaname}}{$tu->{tablename}}{".ts"} += $tu->{s};
}
open(my $fh, ">:encoding(UTF-8)", "index.html.$$");
print_header($fh);
say $fh "<table>";
say $fh "<tr class='header'>";
say $fh "<th class='name'>", "Schema", "</th>";
say $fh "<th class='name'>", "Table", "</th>";
say $fh "<th class='num'>", "Total size (bytes)", "</th>";
say $fh "<th class='num'>", "Table size (bytes)", "</th>";
say $fh "<th class='num'>", "Indexes size (bytes)", "</th>";
say $fh "</tr>";
my $index_usage
= $dbh->selectall_arrayref("
select schemaname,
tablename,
indexname,
pg_total_relation_size(quote_ident(schemaname) || '.' || quote_ident(indexname)) as s
from pg_indexes
",
{ Slice => {} }
);
for my $iu (@$index_usage) {
$du->{$iu->{schemaname}}{".s"} += $iu->{s};
$du->{$iu->{schemaname}}{$iu->{tablename}}{".s"} += $iu->{s};
$du->{$iu->{schemaname}}{$iu->{tablename}}{$iu->{indexname}}{".s"} += $iu->{s};
}
for my $s (sort { $overview->{$b}{''}{total_size} <=> $overview->{$a}{''}{total_size} } keys $overview) {
say $fh "<tr class='schema'>";
say $fh "<td class='name'>", escape($s), "</td>";
say $fh "<td class='name'>", '', "</td>";
say $fh "<td class='num'>", pretty($overview->{$s}{''}{total_size}), "</td>";
say $fh "<td class='num'>", pretty($overview->{$s}{''}{table_size}), "</td>";
say $fh "<td class='num'>", pretty($overview->{$s}{''}{indexes_size}), "</td>";
say $fh "</tr>";
say "<meta charset='utf-8'/>";
say "<style>";
say " .num {";
say " text-align: right;";
say " }";
say " .schema {";
say " background-color: #CCCCCC;";
say " }";
say " .table {";
say " background-color: #E5E5E5;";
say " }";
say "</style>";
for my $t (sort { $overview->{$s}{$b}{total_size} <=> $overview->{$s}{$a}{total_size} } keys $overview->{$s}) {
next unless $t; # schema - we already have that
say "<table>";
for my $schema (sort { $du->{$b}{".s"} <=> $du->{$a}{".s"} }
keys %$du) {
say "<tr class='schema'>";
say "<td class='num'>", pretty($du->{$schema}{".s"}), "</td>";
say "<td class='name'>", escape($schema), "</td>";
for my $table (sort { $du->{$schema}{$b}{".s"} <=> $du->{$schema}{$a}{".s"} }
grep !/^\./,
keys %{$du->{$schema}}) {
say "<tr class='table'>";
say "<td class='num'>", pretty($du->{$schema}{$table}{".s"}), "</td>";
say "<td class='empty'></td>";
say "<td class='name'>", escape($table), "</td>";
if ($du->{$schema}{$table}{".ts"} != $du->{$schema}{$table}{".s"}) {
say "<tr class='table'>";
say "<td class='num'>", pretty($du->{$schema}{$table}{".ts"}), "</td>";
say "<td class='empty'></td>";
say "<td class='empty'></td>";
say "<td class='name'>", "(table)", "</td>";
}
for my $index (sort { $du->{$schema}{$table}{$b}{".s"} <=> $du->{$schema}{$table}{$a}{".s"} }
grep !/^\./,
keys %{$du->{$schema}{$table}}) {
say "<tr class='index'>";
say "<td class='num'>", pretty($du->{$schema}{$table}{$index}{".s"}), "</td>";
say "<td class='empty'></td>";
say "<td class='empty'></td>";
say "<td class='name'>", escape($index), "</td>";
}
say $fh "<tr class='table'>";
say $fh "<td class='name'>", escape($s), "</td>";
say $fh "<td class='name'>", escape($t), "</td>";
say $fh "<td class='num'>", pretty($overview->{$s}{$t}{total_size}), "</td>";
say $fh "<td class='num'>", pretty($overview->{$s}{$t}{table_size}), "</td>";
say $fh "<td class='num'>", pretty($overview->{$s}{$t}{indexes_size}), "</td>";
say $fh "</tr>";
}
}
say "</table>";
say $fh "</table>";
close($fh);
rename "index.html.$$", "index.html";
exit(0);
sub pretty {
my ($n) = @_;
@ -112,4 +99,21 @@ sub escape {
return $s;
}
sub print_header {
my ($fh) = @_;
say $fh "<meta charset='utf-8'/>";
say $fh "<style>";
say $fh " .num {";
say $fh " text-align: right;";
say $fh " }";
say $fh " .schema {";
say $fh " background-color: #CCCCCC;";
say $fh " }";
say $fh " .table {";
say $fh " background-color: #E5E5E5;";
say $fh " }";
say $fh "</style>";
}
# vim: sw=4 tw=132 expandtab