On Thursday February 10 2005 5:01, David Fetter wrote:
> On Thu, Feb 10, 2005 at 05:19:41PM -0500, Tom Lane wrote:
> > David Fetter <[EMAIL PROTECTED]> writes:
> > > I'd be delighted to, but I'm not sure how to see to it
> > > that EXPLAIN gets the CMD_SELECT flag.  What all files
> > > need to change to effect this?  Or have I drastically
> > > misunderstood what's involved?
> >
> > It doesn't.  See
> > http://archives.postgresql.org/pgsql-committers/2005-02/msg0
> >0073.php
>
> Yay!!
>
> Thanks a big bunch, Tom :)

Doodz, u r so phat!  We'd still be working out who
should be invited to the first requirements analysis 
meeting if this were at company X...

This is close but my regexes are not quite right...

CREATE TYPE pg_explain_analyze_in AS (
    exp  text
);

CREATE TYPE pg_explain_analyze_out AS (
        node_id integer,
        node varchar,
        parent_node_id integer,
        level integer,
        index varchar,
        relation varchar,
        plan_startup_cost float,
        plan_total_cost float,
        plan_rows bigint,
        plan_width integer,
        act_startup_cost float,
        act_total_cost float,
        act_rows bigint,
        act_loops bigint,
        condition varchar,
        filter varchar,
        total_time float,
        raw_out varchar
);

CREATE OR REPLACE FUNCTION pg_explain_analyze(query text) RETURNS SETOF 
pg_explain_analyze_out AS $$
DECLARE
    row  pg_explain_analyze_in;
    ret  pg_explain_analyze_out;
    i    integer;
    indent integer;
BEGIN
    i = 0;
    FOR row IN EXECUTE 'EXPLAIN ANALYZE ' || query LOOP
      ret.node_id           := i;
      row.exp               := replace(row.exp, '->  ', '');
      ret.node              := substring(row.exp FROM '[->  ]?(\\S[^\\(:]+) 
\\(');
      ret.parent_node_id    := -1;
      ret.level             := length(substring(row.exp FROM '^(\\s*)\\S'));
      ret.index             := substring(row.exp FROM 'Index Scan using (\\S+) 
on \\S+');
      ret.relation          := substring(row.exp FROM 'Scan using \\S+ on 
(\\S+)');
      ret.plan_startup_cost := substring(row.exp FROM 'cost=(\\d+\\.\\d+)');
      ret.plan_total_cost   := substring(row.exp FROM 
'cost=\\d+\\.\\d+\\.\\.(\\d+\\.\\d+) rows');
      ret.plan_rows         := substring(row.exp FROM ' rows=([[:digit:]]+) 
width');
      ret.plan_width        := substring(row.exp FROM ' width=([[:digit:]]+)');
      ret.act_startup_cost  := substring(row.exp FROM ' width=([[:digit:]]+)');
      ret.act_total_cost    := substring(row.exp FROM ' width=([[:digit:]]+)');
      ret.act_startup_cost  := substring(row.exp FROM 'time=(\\d+\\.\\d+)');
      ret.act_total_cost    := substring(row.exp FROM 
'time=\\d+\\.\\d+\\.\\.(\\d+\\.\\d+) rows');
      ret.act_rows          := substring(row.exp FROM ' rows=([[:digit:]]+) 
loops');
      ret.act_loops         := substring(row.exp FROM ' rows=[[:digit:]]+ 
loops=([[:digit:]]+)\\)');
      ret.condition         := substring(row.exp FROM 'Cond: \\((\\.+)\\)');
      ret.filter            := substring(row.exp FROM 'Filter: \\((\\.*)\\)');
      ret.total_time        := substring(row.exp FROM 'Total runtime: 
(\\d+\\.\\d+) ms');
      ret.raw_out           := row.exp;

      IF substring(row.exp FROM '\\S') IS NOT NULL THEN
          RETURN NEXT ret; 
      END IF;
      i := i + 1;
    END LOOP;
    
    RETURN;
END;
$$ LANGUAGE plpgsql VOLATILE STRICT;


% psql -c "explain analyze select * from foobarbaz_view where id < 3;"
                                                        QUERY PLAN              
                                          
--------------------------------------------------------------------------------------------------------------------------
 Nested Loop  (cost=0.00..15.13 rows=2 width=12) (actual time=0.060..0.090 
rows=2 loops=1)
   ->  Nested Loop  (cost=0.00..9.08 rows=2 width=12) (actual time=0.043..0.059 
rows=2 loops=1)
         ->  Index Scan using baz_pkey on baz  (cost=0.00..3.03 rows=2 width=8) 
(actual time=0.017..0.021 rows=2 loops=1)
               Index Cond: (id < 3)
         ->  Index Scan using bar_pkey on bar  (cost=0.00..3.01 rows=1 width=8) 
(actual time=0.012..0.014 rows=1 loops=2)
               Index Cond: ("outer".bar_id = bar.id)
   ->  Index Scan using foo_pkey on foo  (cost=0.00..3.01 rows=1 width=4) 
(actual time=0.010..0.011 rows=1 loops=2)
         Index Cond: ("outer".foo_id = foo.id)
 Total runtime: 0.226 ms
(9 rows)

% psql -c "SELECT case when node notnull then 
node||'(cost='||plan_startup_cost||'..'||plan_total_cost||' 
rows='||plan_rows||' width='||plan_width||') (actual 
time='||act_startup_cost||'..'||act_total_cost||' rows='||act_rows||' 
loops='||act_loops||' per row='||case when act_rows > 0 then 
to_char(act_total_cost/act_rows, '9.999') else '0.00' end||')' else 'Total 
runtime: '||total_time||' ms' end FROM pg_explain_analyze('select * from 
foobarbaz_view where id < 3');"
                                                          case                  
                                         
-------------------------------------------------------------------------------------------------------------------------
 Nested Loop (cost=0..15.13 rows=2 width=12) (actual time=0.058..0.088 rows=2 
loops=1 per row=  .044)
 Nested Loop (cost=0..9.08 rows=2 width=12) (actual time=0.04..0.056 rows=2 
loops=1 per row=  .028)
 Index Scan using baz_pkey on baz (cost=0..3.03 rows=2 width=8) (actual 
time=0.016..0.02 rows=2 loops=1 per row=  .010)
 
 Index Scan using bar_pkey on bar (cost=0..3.01 rows=1 width=8) (actual 
time=0.011..0.012 rows=1 loops=2 per row=  .012)
 
 Index Scan using foo_pkey on foo (cost=0..3.01 rows=1 width=4) (actual 
time=0.01..0.011 rows=1 loops=2 per row=  .011)
 
 Total runtime: 0.2 ms
(9 rows)



---------------------------(end of broadcast)---------------------------
TIP 6: Have you searched our list archives?

               http://archives.postgresql.org

Reply via email to