Search Postgresql Archives

Re: Understanding EXPLAIN ANALYZE output

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In article <20050211222117.GF7055@xxxxxxxxx>,
Martijn van Oosterhout <kleptog@xxxxxxxxx> writes:

> There's one corner case you need to make sure you handle. In the plan
> that started this thread there's a query node marked (never executed).
> That will affect yout regex a bit. an that case you should probably
> return NULLs. (It might do that, I havn't run the code through
> carefully).

Ah, good point.  Here's a version which should do that.  It also tries
to extract the index name.

------------------------ snip snip snipety-snip --------------------------

CREATE TYPE expl_t AS (
  id INT,
  level INT,
  type TEXT,
  indx TEXT,
  relation TEXT,
  cost1 FLOAT,
  cost2 FLOAT,
  rows INT,
  width INT,
  atime1 FLOAT,
  atime2 FLOAT,
  arows INT,
  loops INT,
  cont TEXT
);

CREATE OR REPLACE FUNCTION pg_explain_analyze(TEXT) RETURNS SETOF expl_t AS $$
  my $sql = $_[0];
  my $rv = spi_exec_query('SELECT current_database()');
  my $db = $rv->{rows}[0]->{current_database};
  # Grab EXPLAIN output
  use strict;
  use warnings;
  use DBI;
  my $dbh = DBI->connect("DBI:Pg:dbname=$db", "", "", {
    AutoCommit => 0,
    PrintError => 0,
    RaiseError => 1,
  });
  my $sth = $dbh->prepare("EXPLAIN ANALYZE $sql");
  $sth->execute();
  my @res = ();
  my @nm = qw(type indx relation cost1 cost2 rows width atime1 atime2 arows loops);
  my $cnt = 0;
  my @plen = (0);
  while (my $res = $sth->fetchrow_arrayref) {
    $cnt++;
    my @a = $res->[0] =~ m{^
      (?:(\s+)->\s\s)?              # Prefix
      (\S+(?:\s\S+)?)               # Operation
      (?:\susing\s(.+?))?           # Index Scan using ixname
      (?:\son\s(\S+)(?:\s\S+)?)?    # on table [alias]
      \s\s                          # Estimations:
      \(cost=(\d+\.\d+)\.\.(\d+\.\d+)\srows=(\d+)\swidth=(\d+)\)
      \s                            # Actual values:
      \((.+?)\)
    $}x;
    unless (@a) {
      $_ = $res->[0];
      next if /^Total runtime: \d+\.\d+ ms$/;
      s/^\s+//;
      if (defined $res[$#res]->{cont}) {
        $res[$#res]->{cont} .= ", $_";
      } else {
        $res[$#res]->{cont} = $_;
      }
      next;
    }
    my @x = $a[8] =~ m{actual\stime=(\d+\.\d+)\.\.(\d+\.\d+)\srows=(\d+)\sloops=(\d+)$};
    splice @a, 8, 1, @x;
    my $pref = shift @a || "";
    my $pl = length $pref;
    # Process prefix
    my $lvl = 0;
    if ($pl > $plen[$#plen]) {
      push @plen, $pl;
      $lvl = $#plen;
    } else {
      for my $ix (0 .. $#plen) {
        next unless $plen[$ix] == $pl;
        $lvl = $ix;
        last;
      }
    }
    my %elt = (id => $cnt, level => $lvl);
    $elt{$nm[$_]} = $a[$_] for (0..$#nm);
    push @res, \%elt;
  }
  $dbh->disconnect;
  return \@res;
$$ LANGUAGE "plperlu";


---------------------------(end of broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
    (send "unregister YourEmailAddressHere" to majordomo@xxxxxxxxxxxxxx)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Postgresql Jobs]     [Postgresql Admin]     [Postgresql Performance]     [Linux Clusters]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Postgresql & PHP]     [Yosemite]
  Powered by Linux