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